diff --git a/src/App.config b/src/App.config
index 8e15646..bae5d6d 100644
--- a/src/App.config
+++ b/src/App.config
@@ -1,6 +1,6 @@
-
+
-
+
-
\ No newline at end of file
+
diff --git a/src/Form1.Designer.cs b/src/Form1.Designer.cs
deleted file mode 100644
index 2cd4e3e..0000000
--- a/src/Form1.Designer.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-namespace JuicyGraphics {
- partial class mainForm {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing) {
- if (disposing && (components != null)) {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent() {
- this.canvas2 = new JuicyGraphics.canvas();
- ((System.ComponentModel.ISupportInitialize)(this.canvas2)).BeginInit();
- this.SuspendLayout();
- //
- // canvas2
- //
- this.canvas2.Dock = System.Windows.Forms.DockStyle.Fill;
- this.canvas2.Location = new System.Drawing.Point(0, 0);
- this.canvas2.Name = "canvas2";
- this.canvas2.Size = new System.Drawing.Size(704, 521);
- this.canvas2.TabIndex = 3;
- this.canvas2.Text = "canvas2";
- //
- // mainForm
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(704, 521);
- this.Controls.Add(this.canvas2);
- this.Name = "mainForm";
- this.Text = "JuicyGraphics";
- ((System.ComponentModel.ISupportInitialize)(this.canvas2)).EndInit();
- this.ResumeLayout(false);
-
- }
-
- #endregion
- private canvas canvas2;
- }
-}
-
diff --git a/src/JuicyGraphics.csproj b/src/JuicyGraphics.csproj
index 24b93e2..0534749 100644
--- a/src/JuicyGraphics.csproj
+++ b/src/JuicyGraphics.csproj
@@ -8,8 +8,9 @@
WinExe
JuicyGraphics
JuicyGraphics
- v4.5
+ v4.6.1
512
+
AnyCPU
@@ -31,9 +32,14 @@
prompt
4
+
+
+
+
+
@@ -45,16 +51,21 @@
-
+
+
+
+
+
+
Component
-
+
Form
-
+
Form1.cs
-
+
@@ -80,7 +91,7 @@
-
+
Form1.cs
@@ -91,6 +102,7 @@
True
Resources.resx
+ True
SettingsSingleFileGenerator
@@ -105,6 +117,8 @@
-
+
+
+
\ No newline at end of file
diff --git a/src/Program.cs b/src/JuicyGraphics/Program.cs
similarity index 100%
rename from src/Program.cs
rename to src/JuicyGraphics/Program.cs
diff --git a/src/JuicyGraphics/renderer/camera2D.cs b/src/JuicyGraphics/renderer/camera2D.cs
new file mode 100644
index 0000000..d430f27
--- /dev/null
+++ b/src/JuicyGraphics/renderer/camera2D.cs
@@ -0,0 +1,32 @@
+using SharpGL;
+using System.Numerics;
+
+namespace Graphics {
+ class camera2D {
+ protected Matrix mat;
+
+ public Vector2 translation {
+ get {
+ return new Vector2((float)mat[0, 3], (float)mat[1, 3]);
+ }
+ set {
+ mat[0, 3] = value.X;
+ mat[1, 3] = value.Y;
+ }
+ }
+
+ public double scale {
+ get {
+ return mat[0, 0];
+ }
+ set {
+ mat[0, 0] = value;
+ mat[1, 1] = value;
+ }
+ }
+
+ public camera2D() {
+ mat = new Matrix(Matrix.Identity(4));
+ }
+ }
+}
diff --git a/src/JuicyGraphics/renderer/iGraphicalObject.cs b/src/JuicyGraphics/renderer/iGraphicalObject.cs
new file mode 100644
index 0000000..23a6cc9
--- /dev/null
+++ b/src/JuicyGraphics/renderer/iGraphicalObject.cs
@@ -0,0 +1,7 @@
+using SharpGL;
+
+namespace Graphics.Objects {
+ interface iGraphicalObject {
+ void render(renderCam context);
+ }
+}
diff --git a/src/JuicyGraphics/renderer/line.cs b/src/JuicyGraphics/renderer/line.cs
new file mode 100644
index 0000000..ac05b4c
--- /dev/null
+++ b/src/JuicyGraphics/renderer/line.cs
@@ -0,0 +1,96 @@
+using SharpGL;
+using System.Numerics;
+
+namespace Graphics.Objects {
+ class line : iGraphicalObject {
+
+ #region fields
+
+ Vector2 pt01;
+ Vector2 pt02;
+ double thickness01;
+ double thickness02;
+ double tilt01;
+ double tilt02;
+
+ #endregion
+
+ #region properties
+
+ #endregion
+
+ #region constructors
+ public line(Vector2 startPoint, Vector2 endPoint) {
+ pt01 = startPoint;
+ pt02 = endPoint;
+ thickness01 = 1.0;
+ thickness02 = 1.0;
+ tilt01 = 0.0;
+ tilt02 = 0.0;
+ }
+
+ public line(Vector2 startPoint, Vector2 endPoint, double thickness) {
+ pt01 = startPoint;
+ pt02 = endPoint;
+ thickness01 = thickness;
+ thickness02 = thickness;
+ tilt01 = 0.0;
+ tilt02 = 0.0;
+ }
+
+ public enum valueing { defineLinearThickness, defineBothTilts }
+
+ public line(Vector2 startPoint, Vector2 endPoint,
+ valueing defineType, double startPointParam, double endPointParam) {
+ pt01 = startPoint;
+ pt02 = endPoint;
+ switch (defineType) {
+ case valueing.defineLinearThickness:
+ thickness01 = startPointParam;
+ thickness02 = endPointParam;
+ tilt01 = 0.0;
+ tilt02 = 0.0;
+ break;
+ case valueing.defineBothTilts:
+ thickness01 = 1.0;
+ thickness02 = 1.0;
+ tilt01 = startPointParam;
+ tilt02 = endPointParam;
+ break;
+ default:
+ thickness01 = 1.0;
+ thickness02 = 1.0;
+ tilt01 = 0.0;
+ tilt02 = 0.0;
+ break;
+ }
+ }
+
+ public line(Vector2 startPoint, Vector2 endPoint,
+ double thickness, double tiltOfStartPoint, double tiltOfEndPoint) {
+ pt01 = startPoint;
+ pt02 = endPoint;
+ thickness01 = thickness;
+ thickness02 = thickness;
+ tilt01 = tiltOfStartPoint;
+ tilt02 = tiltOfEndPoint;
+ }
+
+ public line(Vector2 startPoint, Vector2 endPoint,
+ double thicknessOfStartPoint, double thicknessOfEndPoint,
+ double tiltOfStartPoint, double tiltOfEndPoint) {
+ pt01 = startPoint;
+ pt02 = endPoint;
+ thickness01 = thicknessOfStartPoint;
+ thickness02 = thicknessOfEndPoint;
+ tilt01 = tiltOfStartPoint;
+ tilt02 = tiltOfEndPoint;
+ }
+
+ #endregion
+
+ public void render(renderCam context) {
+ context.drawQuad(pt01, pt01 + new Vector2(0.03f, 0), pt02 + new Vector2(0.03f, 0), pt02);
+ }
+ }
+}
diff --git a/src/JuicyGraphics/renderer/renderCam.cs b/src/JuicyGraphics/renderer/renderCam.cs
new file mode 100644
index 0000000..ae97d96
--- /dev/null
+++ b/src/JuicyGraphics/renderer/renderCam.cs
@@ -0,0 +1,37 @@
+using System.Windows.Forms;
+using System.Numerics;
+using SharpGL;
+
+
+namespace Graphics {
+ class renderCam : camera2D {
+
+ OpenGL gl;
+ Control ownerControl;
+
+ public renderCam(OpenGL glContext, Control owner) : base() {
+ gl = glContext;
+ ownerControl = owner;
+ }
+
+ public void attacheMatrix() {
+ gl.MultMatrix(mat);
+ }
+
+ public void drawTriangle(Vector2 corner01, Vector2 corner02, Vector2 corner03) {
+ gl.Vertex(corner01);
+ gl.Vertex(corner02);
+ gl.Vertex(corner03);
+ }
+
+ public void drawQuad(Vector2 corner01, Vector2 corner02, Vector2 corner03, Vector2 corner04) {
+ gl.Vertex(corner01);
+ gl.Vertex(corner02);
+ gl.Vertex(corner03);
+ gl.Vertex(corner03);
+ gl.Vertex(corner04);
+ gl.Vertex(corner01);
+ }
+
+ }
+}
diff --git a/src/JuicyGraphics/ui/Form1.Designer.cs b/src/JuicyGraphics/ui/Form1.Designer.cs
new file mode 100644
index 0000000..dc29d44
--- /dev/null
+++ b/src/JuicyGraphics/ui/Form1.Designer.cs
@@ -0,0 +1,138 @@
+namespace JuicyGraphics {
+ partial class mainForm {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.tabControl1 = new System.Windows.Forms.TabControl();
+ this.tabPage1 = new System.Windows.Forms.TabPage();
+ this.canvas1 = new JuicyGraphics.canvas();
+ this.tabPage2 = new System.Windows.Forms.TabPage();
+ this.menuStrip1.SuspendLayout();
+ this.tabControl1.SuspendLayout();
+ this.tabPage1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.canvas1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.fileToolStripMenuItem,
+ this.editToolStripMenuItem});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Size = new System.Drawing.Size(704, 24);
+ this.menuStrip1.TabIndex = 4;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // fileToolStripMenuItem
+ //
+ this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
+ this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
+ this.fileToolStripMenuItem.Text = "File";
+ //
+ // editToolStripMenuItem
+ //
+ this.editToolStripMenuItem.Name = "editToolStripMenuItem";
+ this.editToolStripMenuItem.Size = new System.Drawing.Size(39, 20);
+ this.editToolStripMenuItem.Text = "Edit";
+ //
+ // tabControl1
+ //
+ this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.tabControl1.Controls.Add(this.tabPage1);
+ this.tabControl1.Controls.Add(this.tabPage2);
+ this.tabControl1.Location = new System.Drawing.Point(13, 28);
+ this.tabControl1.Name = "tabControl1";
+ this.tabControl1.SelectedIndex = 0;
+ this.tabControl1.Size = new System.Drawing.Size(679, 481);
+ this.tabControl1.TabIndex = 5;
+ //
+ // tabPage1
+ //
+ this.tabPage1.Controls.Add(this.canvas1);
+ this.tabPage1.Location = new System.Drawing.Point(4, 22);
+ this.tabPage1.Name = "tabPage1";
+ this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
+ this.tabPage1.Size = new System.Drawing.Size(671, 455);
+ this.tabPage1.TabIndex = 0;
+ this.tabPage1.Text = "Scene Editor";
+ this.tabPage1.UseVisualStyleBackColor = true;
+ //
+ // canvas1
+ //
+ this.canvas1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.canvas1.Location = new System.Drawing.Point(7, 7);
+ this.canvas1.Name = "canvas1";
+ this.canvas1.Size = new System.Drawing.Size(508, 442);
+ this.canvas1.TabIndex = 0;
+ this.canvas1.Text = "canvas1";
+ //
+ // tabPage2
+ //
+ this.tabPage2.Location = new System.Drawing.Point(4, 22);
+ this.tabPage2.Name = "tabPage2";
+ this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
+ this.tabPage2.Size = new System.Drawing.Size(671, 455);
+ this.tabPage2.TabIndex = 1;
+ this.tabPage2.Text = "Object Editor";
+ this.tabPage2.UseVisualStyleBackColor = true;
+ //
+ // mainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(704, 521);
+ this.Controls.Add(this.tabControl1);
+ this.Controls.Add(this.menuStrip1);
+ this.MainMenuStrip = this.menuStrip1;
+ this.Name = "mainForm";
+ this.Text = "JuicyGraphics";
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.tabControl1.ResumeLayout(false);
+ this.tabPage1.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.canvas1)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem;
+ private System.Windows.Forms.TabControl tabControl1;
+ private System.Windows.Forms.TabPage tabPage1;
+ private canvas canvas1;
+ private System.Windows.Forms.TabPage tabPage2;
+ }
+}
+
diff --git a/src/Form1.cs b/src/JuicyGraphics/ui/Form1.cs
similarity index 100%
rename from src/Form1.cs
rename to src/JuicyGraphics/ui/Form1.cs
diff --git a/src/Form1.resx b/src/JuicyGraphics/ui/Form1.resx
similarity index 96%
rename from src/Form1.resx
rename to src/JuicyGraphics/ui/Form1.resx
index 1af7de1..d5494e3 100644
--- a/src/Form1.resx
+++ b/src/JuicyGraphics/ui/Form1.resx
@@ -117,4 +117,7 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ 17, 17
+
\ No newline at end of file
diff --git a/src/JuicyGraphics/ui/canvas.cs b/src/JuicyGraphics/ui/canvas.cs
new file mode 100644
index 0000000..13df864
--- /dev/null
+++ b/src/JuicyGraphics/ui/canvas.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Windows.Forms;
+using System.Windows;
+using SharpGL.Enumerations;
+using SharpGL.Version;
+using SharpGL;
+using System.ComponentModel;
+using Graphics;
+using Graphics.Objects;
+using System.Numerics;
+using System.Drawing;
+
+namespace JuicyGraphics {
+ class canvas : Control, ISupportInitialize {
+
+ OpenGL GL = new OpenGL();
+ renderCam rc;
+
+ public canvas() {
+ SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+ SetStyle(ControlStyles.UserPaint, true);
+ InitializeOpenGL();
+ rc = new renderCam(GL, this);
+ }
+
+ void InitializeOpenGL() {
+ GL.Create(OpenGLVersion.OpenGL4_3, RenderContextType.NativeWindow, Width, Height, 32, this.Handle);
+ GL.ShadeModel(OpenGL.GL_SMOOTH);
+ GL.ClearDepth(1.0f);
+ GL.Enable(OpenGL.GL_DEPTH_TEST);
+ GL.DepthFunc(OpenGL.GL_LEQUAL);
+ GL.Hint(OpenGL.GL_PERSPECTIVE_CORRECTION_HINT, OpenGL.GL_NICEST);
+ GL.Viewport(0, 0, Width, Height);
+ }
+
+ bool renderingForDesigner() {
+ if (this == null)
+ return false;
+ if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
+ return true;
+ Control p = this.Parent;
+ while (p != null) {
+ if (p.GetType().FullName.Contains(".DesignerFrame"))
+ return true;
+ p = p.Parent;
+ }
+ return false;
+ }
+
+ protected override void OnPaintBackground(PaintEventArgs e) {
+ if (renderingForDesigner()) { base.OnPaintBackground(e); }
+ return;
+ }
+
+ protected override void OnPaint(PaintEventArgs e) {
+ if (renderingForDesigner()) {
+ SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+ SetStyle(ControlStyles.UserPaint, true);
+ InitializeOpenGL();
+ }
+ GL.LoadIdentity();
+ GL.Ortho(-(Width / 2160.0), Width / 2160.0,
+ -(Height / 2160.0), Height / 2160.0,
+ -1, 1);
+ if (rc != null)
+ rc.attacheMatrix();
+ GL.MakeCurrent();
+ GL.ClearColor(0.3f, 0.35f, 0.7f, 1f);
+ GL.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
+
+ GL.Begin(BeginMode.Triangles);
+ GL.Color(0.9, 0.83, 0.1);
+ GL.Vertex(1.0, 1.0);
+ GL.Vertex(-1.0, -1.0);
+ GL.Vertex(-1.0, 1.0);
+
+ GL.Color(0, 0, 0);
+ line testLine = new line(new Vector2(-0.4f, 0.4f), new Vector2(0.4f, -0.4f));
+ testLine.render(rc);
+
+ GL.End();
+ GL.Flush();
+
+ var handleDeviceContext = e.Graphics.GetHdc();
+ GL.Blit(handleDeviceContext);
+ e.Graphics.ReleaseHdc(handleDeviceContext);
+ }
+
+ protected override void OnSizeChanged(EventArgs e) {
+ if (GL.RenderContextProvider == null)
+ return;
+ GL.SetDimensions(Width, Height);
+ GL.Viewport(0, 0, Width, Height);
+ Invalidate();
+ }
+
+ enum mouseInteractionMode { none, left, middle, right };
+ mouseInteractionMode pressedMouseButton = mouseInteractionMode.none;
+ Point prevMousePosition = Point.Empty;
+
+ protected override void OnMouseDown(MouseEventArgs e) {
+ switch (e.Button) {
+ case MouseButtons.Left:
+ pressedMouseButton = mouseInteractionMode.left;
+ break;
+ case MouseButtons.Middle:
+ pressedMouseButton = mouseInteractionMode.middle;
+ break;
+ case MouseButtons.Right:
+ pressedMouseButton = mouseInteractionMode.right;
+ break;
+ }
+ prevMousePosition = MousePosition;
+ }
+
+ protected override void OnMouseMove(MouseEventArgs e) {
+ switch (pressedMouseButton) {
+ case mouseInteractionMode.left:
+ break;
+ case mouseInteractionMode.middle:
+ rc.translation += new Vector2(MousePosition.X - prevMousePosition.X,
+ prevMousePosition.Y - MousePosition.Y) / 1080.0f;
+ Invalidate();
+ break;
+ case mouseInteractionMode.right:
+ break;
+ }
+ prevMousePosition = MousePosition;
+ }
+
+ protected override void OnMouseUp(MouseEventArgs e) {
+ switch (e.Button) {
+ case MouseButtons.Left:
+ if (pressedMouseButton == mouseInteractionMode.left)
+ pressedMouseButton = mouseInteractionMode.none;
+ break;
+ case MouseButtons.Middle:
+ if (pressedMouseButton == mouseInteractionMode.middle)
+ pressedMouseButton = mouseInteractionMode.none;
+ break;
+ case MouseButtons.Right:
+ if (pressedMouseButton == mouseInteractionMode.right)
+ pressedMouseButton = mouseInteractionMode.none;
+ break;
+ }
+ }
+
+ protected override void OnMouseWheel(MouseEventArgs e) {
+ rc.scale *= Math.Pow(1.0008, e.Delta);
+ Invalidate();
+ }
+
+ public void BeginInit() { }
+
+ public void EndInit() {
+ InitializeOpenGL();
+ OnSizeChanged(null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Properties/Resources.Designer.cs b/src/Properties/Resources.Designer.cs
index 808f911..3293a32 100644
--- a/src/Properties/Resources.Designer.cs
+++ b/src/Properties/Resources.Designer.cs
@@ -9,8 +9,9 @@
//------------------------------------------------------------------------------
namespace JuicyGraphics.Properties {
-
-
+ using System;
+
+
///
/// A strongly-typed resource class, for looking up localized strings, etc.
///
@@ -22,29 +23,29 @@ namespace JuicyGraphics.Properties {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
-
+
private static global::System.Resources.ResourceManager resourceMan;
-
+
private static global::System.Globalization.CultureInfo resourceCulture;
-
+
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
-
+
///
/// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
- if ((resourceMan == null)) {
+ if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JuicyGraphics.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
-
+
///
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
diff --git a/src/Properties/Settings.Designer.cs b/src/Properties/Settings.Designer.cs
index d1fd434..37e1639 100644
--- a/src/Properties/Settings.Designer.cs
+++ b/src/Properties/Settings.Designer.cs
@@ -9,14 +9,14 @@
//------------------------------------------------------------------------------
namespace JuicyGraphics.Properties {
-
-
+
+
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
-
+
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
+
public static Settings Default {
get {
return defaultInstance;
diff --git a/src/SharpGL/Matrix.cs b/src/SharpGL/Matrix.cs
new file mode 100644
index 0000000..b7de6a4
--- /dev/null
+++ b/src/SharpGL/Matrix.cs
@@ -0,0 +1,2046 @@
+using System;
+using System.Collections.Generic;
+
+namespace SharpGL {
+ ///
+ /// A 4x4 matrix.
+ ///
+ [Serializable()]
+ #region "Exception in the Library"
+ class MatrixLibraryExceptions : ApplicationException { public MatrixLibraryExceptions(string message) : base(message) { } }
+
+ // The Exceptions in this Class
+ class MatrixNullException : ApplicationException {
+ public MatrixNullException() :
+ base("To do this operation, matrix can not be null") { }
+ }
+ class MatrixDimensionException : ApplicationException {
+ public MatrixDimensionException() :
+ base("Dimension of the two matrices not suitable for this operation !") { }
+ }
+ class MatrixNotSquare : ApplicationException {
+ public MatrixNotSquare() :
+ base("To do this operation, matrix must be a square matrix !") { }
+ }
+ class MatrixDeterminentZero : ApplicationException {
+ public MatrixDeterminentZero() :
+ base("Determinent of matrix equals zero, inverse can't be found !") { }
+ }
+ class VectorDimensionException : ApplicationException {
+ public VectorDimensionException() :
+ base("Dimension of matrix must be [3 , 1] to do this operation !") { }
+ }
+ class MatrixSingularException : ApplicationException {
+ public MatrixSingularException() :
+ base("Matrix is singular this operation cannot continue !") { }
+ }
+ #endregion
+
+ ///
+ /// Matrix Library .Net v2.0 By Anas Abidi, 2004.
+ ///
+ /// The Matrix Library contains Class Matrix which provides many
+ /// static methods for making various matrix operations on objects
+ /// derived from the class or on arrays defined as double. The
+ /// '+','-','*' operators are overloaded to work with the objects
+ /// derived from the matrix class.
+ ///
+ public class Matrix {
+
+ ///
+ /// Returns a hash code for this instance.
+ ///
+ ///
+ /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+ ///
+ public override int GetHashCode() {
+ return in_Mat.GetHashCode();
+ }
+
+ ///
+ /// The matrix.
+ ///
+ private double[,] in_Mat;
+
+ ///
+ /// Matrix object constructor, constructs an empty
+ /// matrix with dimensions: rows = noRows and cols = noCols.
+ ///
+ /// no. of rows in this matrix
+ /// no. of columns in this matrix
+ public Matrix(int noRows, int noCols) {
+ this.in_Mat = new double[noRows, noCols];
+ }
+
+ ///
+ /// Matrix object constructor, constructs a matrix from an
+ /// already defined array object.
+ ///
+ /// the array the matrix will contain
+ public Matrix(double[,] Mat) {
+ this.in_Mat = (double[,])Mat.Clone();
+ }
+
+ public Matrix(Matrix matrix) {
+ this.in_Mat = (double[,])matrix.in_Mat.Clone();
+ }
+
+ ///
+ /// Set or get an element from the matrix
+ ///
+ public double this[int Row, int Col] {
+ get { return this.in_Mat[Row, Col]; }
+ set { this.in_Mat[Row, Col] = value; }
+ }
+
+ public float this[int Row, int Col, bool asFloat] {
+ get { return (float)this.in_Mat[Row, Col]; }
+ set { this.in_Mat[Row, Col] = value; }
+ }
+
+ ///
+ /// Creates a matrix from a column major array.
+ ///
+ /// The column major array.
+ /// The rows.
+ /// The columns.
+ /// The matrix.
+ public static Matrix FromColumnMajorArray(double[] columnMajorArray, int rows, int columns) {
+ // Create the matrix.
+ Matrix matrix = new Matrix(rows, columns);
+
+ // Set the values.
+ int index = 0;
+ for (int i = 0; i < rows; i++)
+ for (int j = 0; j < columns; j++)
+ matrix[i, j] = columnMajorArray[index++];
+
+ // Return the matrix.
+ return matrix;
+ }
+
+ ///
+ /// Creates a matrix from a row major array.
+ ///
+ /// The column major array.
+ /// The rows.
+ /// The columns.
+ /// The matrix.
+ public static Matrix FromRowMajorArray(double[] rowMajorArray, int rows, int columns) {
+ // Create the matrix.
+ Matrix matrix = new Matrix(rows, columns);
+
+ // Set the values.
+ int index = 0;
+ for (int i = 0; i < columns; i++)
+ for (int j = 0; j < rows; j++)
+ matrix[j, i] = rowMajorArray[index++];
+
+ // Return the matrix.
+ return matrix;
+ }
+
+ ///
+ /// Creates a matrix from a segment of another matrix.
+ ///
+ /// The RHS.
+ /// The rows.
+ /// The cols.
+ public void FromOtherMatrix(Matrix rhs, int rows, int cols) {
+ // Check dimensions.
+ if (rows > Rows || rows > rhs.Rows || cols > Columns || cols > rhs.Columns)
+ throw new MatrixDimensionException();
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < cols; j++) {
+ this[i, j] = rhs[i, j];
+ }
+ }
+ }
+
+ #region "Public Properties"
+ ///
+ /// Set or get the no. of rows in the matrix.
+ /// Warning: Setting this property will delete all of
+ /// the elements of the matrix and set them to zero.
+ ///
+ public int Rows {
+ get { return this.in_Mat.GetUpperBound(0) + 1; }
+ set { this.in_Mat = new double[value, this.in_Mat.GetUpperBound(0)]; }
+ }
+
+ ///
+ /// Set or get the no. of columns in the matrix.
+ /// Warning: Setting this property will delete all of
+ /// the elements of the matrix and set them to zero.
+ ///
+ public int Columns {
+ get { return this.in_Mat.GetUpperBound(1) + 1; }
+ set { this.in_Mat = new double[this.in_Mat.GetUpperBound(0), value]; }
+ }
+
+ ///
+ /// This property returns the matrix as an array.
+ ///
+ public double[,] AsArray {
+ get { return this.in_Mat; }
+ }
+
+ public double[] As1DArray {
+ get {
+ double[] _m = new double[in_Mat.Length];
+ for (int row = 0; row < in_Mat.GetLength(1); row++) {
+ for (int column = 0; column < in_Mat.GetLength(0); column++) {
+ _m[column + row * in_Mat.GetLength(0)] = in_Mat[column, row];
+ }
+ }
+ return _m;
+ }
+ }
+
+ ///
+ /// Gets the matrix as a row major array.
+ ///
+ public double[] AsRowMajorArray {
+ get {
+ // Storage for the array.
+ List ar = new List();
+
+ // Create the array.
+ for (int i = 0; i < Rows; i++)
+ for (int j = 0; j < Columns; j++)
+ ar.Add(this[i, j]);
+
+ // Return the array.
+ return ar.ToArray();
+ }
+ }
+
+ ///
+ /// Gets the matrix as a row major array.
+ ///
+ public float[] AsRowMajorArrayFloat {
+ get {
+ // Storage for the array.
+ List ar = new List();
+
+ // Create the array.
+ for (int i = 0; i < Rows; i++)
+ for (int j = 0; j < Columns; j++)
+ ar.Add((float)this[i, j]);
+
+ // Return the array.
+ return ar.ToArray();
+ }
+ }
+
+ ///
+ /// Gets the matrix as a column major array.
+ ///
+ public double[] AsColumnMajorArray {
+ get {
+ // Storage for the array.
+ List ar = new List();
+
+ // Create the array.
+ for (int i = 0; i < Columns; i++)
+ for (int j = 0; j < Rows; j++)
+ ar.Add(this[j, i]);
+
+ // Return the array.
+ return ar.ToArray();
+ }
+ }
+
+ ///
+ /// Gets the matrix as a column major array.
+ ///
+ public float[] AsColumnMajorArrayFloat {
+ get {
+ // Storage for the array.
+ List ar = new List();
+
+ // Create the array.
+ for (int i = 0; i < Columns; i++)
+ for (int j = 0; j < Rows; j++)
+ ar.Add((float)this[j, i]);
+
+ // Return the array.
+ return ar.ToArray();
+ }
+ }
+
+ #endregion
+
+ #region copy
+
+ public float TempSVD() {
+ // this is a simple svd.
+ // Not complete but fast and reasonable.
+ // See comment in Matrix3d.
+ return (float)Math.Sqrt(
+ (float)((this[0, 0] * this[0, 0]) + (this[0, 1] * this[0, 1]) + (this[0, 2] * this[0, 2]) +
+ (this[1, 0] * this[1, 0]) + (this[1, 1] * this[1, 1]) + (this[1, 2] * this[1, 2]) +
+ (this[2, 0] * this[2, 0]) + (this[2, 1] * this[2, 1]) + (this[2, 2] * this[2, 2])) / 3.0f);
+ }
+
+ public void Multiply(float value, int rows, int cols) {
+ int myrows, mycols;
+
+ //Find The dimensions !!
+ try {
+ Find_R_C(this.in_Mat, out myrows, out mycols);
+ }
+ catch {
+ throw new MatrixNullException();
+ }
+
+ if (rows > myrows || cols > mycols)
+ throw new ArgumentException();
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < cols; j++) {
+ this[i, j] *= value;
+ }
+ }
+ }
+
+ #endregion
+
+
+ #region "Find Rows and Columns in a Matrix"
+ private static void Find_R_C(double[] Mat, out int Row) {
+ Row = Mat.GetUpperBound(0);
+ }
+
+ private static void Find_R_C(double[,] Mat, out int Row, out int Col) {
+ Row = Mat.GetUpperBound(0);
+ Col = Mat.GetUpperBound(1);
+ }
+ #endregion
+
+ #region "Change 1D array ([n]) to/from 2D array [n,1]"
+
+ ///
+ /// Returns the 2D form of a 1D array. i.e. array with
+ /// dimension[n] is returned as an array with dimension [n,1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ ///
+ /// the array to convert, with dimesion [n]
+ ///
+ /// the same array but with [n,1] dimension
+ public static double[,] OneD_2_TwoD(double[] Mat) {
+ int Rows;
+ //Find The dimensions !!
+ try { Find_R_C(Mat, out Rows); }
+ catch { throw new MatrixNullException(); }
+
+ double[,] Sol = new double[Rows + 1, 1];
+
+ for (int i = 0; i <= Rows; i++) {
+ Sol[i, 0] = Mat[i];
+ }
+
+ return Sol;
+ }
+
+ ///
+ /// Returns the 1D form of a 2D array. i.e. array with
+ /// dimension[n,1] is returned as an array with dimension [n].
+ /// In case of an error the error is raised as an exception.
+ ///
+ ///
+ /// the array to convert, with dimesions [n,1]
+ ///
+ /// the same array but with [n] dimension
+ public static double[] TwoD_2_OneD(double[,] Mat) {
+ int Rows;
+ int Cols;
+ //Find The dimensions !!
+ try { Find_R_C(Mat, out Rows, out Cols); }
+ catch { throw new MatrixNullException(); }
+
+ if (Cols != 0) throw new MatrixDimensionException();
+
+ double[] Sol = new double[Rows + 1];
+
+ for (int i = 0; i <= Rows; i++) {
+ Sol[i] = Mat[i, 0];
+ }
+ return Sol;
+ }
+ #endregion
+
+ #region "Identity Matrix"
+
+ ///
+ /// Sets the identity matrix as the identity matrix. It must be N x N (i.e.
+ /// square).
+ ///
+ public void SetIdentity() {
+ // We must be n by n.
+ if (Rows != Columns || Rows == 0)
+ throw new MatrixDimensionException();
+
+ // Set the identity.
+ for (int i = 0; i < Rows; i++)
+ for (int j = 0; j < Columns; j++)
+ this[i, j] = i == j ? 1 : 0;
+ }
+
+ ///
+ /// Returns an Identity matrix with dimensions [n,n] in the from of an array.
+ ///
+ /// the no. of rows or no. cols in the matrix
+ /// An identity Matrix with dimensions [n,n] in the form of an array
+ public static double[,] Identity(int n) {
+ double[,] temp = new double[n, n];
+ for (int i = 0; i < n; i++) temp[i, i] = 1;
+ return temp;
+ }
+
+ #endregion
+
+ #region "Add Matrices"
+ ///
+ /// Returns the summation of two matrices with compatible
+ /// dimensions.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First array in the summation
+ /// Second array in the summation
+ /// Sum of Mat1 and Mat2 as an array
+ public static double[,] Add(double[,] Mat1, double[,] Mat2) {
+ double[,] sol;
+ int i, j;
+ int Rows1, Cols1;
+ int Rows2, Cols2;
+
+ //Find The dimensions !!
+ try {
+ Find_R_C(Mat1, out Rows1, out Cols1);
+ Find_R_C(Mat2, out Rows2, out Cols2);
+ }
+ catch {
+ throw new MatrixNullException();
+ }
+
+ if (Rows1 != Rows2 || Cols1 != Cols2) throw new MatrixDimensionException();
+
+ sol = new double[Rows1 + 1, Cols1 + 1];
+
+ for (i = 0; i <= Rows1; i++)
+ for (j = 0; j <= Cols1; j++) {
+ sol[i, j] = Mat1[i, j] + Mat2[i, j];
+ }
+
+ return sol;
+ }
+
+ ///
+ /// Returns the summation of two matrices with compatible
+ /// dimensions.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First matrix in the summation
+ /// Second matrix in the summation
+ /// Sum of Mat1 and Mat2 as a Matrix object
+ public static Matrix Add(Matrix Mat1, Matrix Mat2) { return new Matrix(Add(Mat1.in_Mat, Mat2.in_Mat)); }
+
+ ///
+ /// Returns the summation of two matrices with compatible
+ /// dimensions.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First Matrix object in the summation
+ /// Second Matrix object in the summation
+ /// Sum of Mat1 and Mat2 as a Matrix object
+ public static Matrix operator +(Matrix Mat1, Matrix Mat2) { return new Matrix(Add(Mat1.in_Mat, Mat2.in_Mat)); }
+ #endregion
+
+ #region "Subtract Matrices"
+
+ ///
+ /// Returns the difference of two matrices with compatible
+ /// dimensions.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First array in the subtraction
+ /// Second array in the subtraction
+ /// Difference of Mat1 and Mat2 as an array
+ public static double[,] Subtract(double[,] Mat1, double[,] Mat2) {
+ double[,] sol;
+ int i, j;
+ int Rows1, Cols1;
+ int Rows2, Cols2;
+
+ //Find The dimensions !!
+ try {
+ Find_R_C(Mat1, out Rows1, out Cols1);
+ Find_R_C(Mat2, out Rows2, out Cols2);
+ }
+ catch {
+ throw new MatrixNullException();
+ }
+
+ if (Rows1 != Rows2 || Cols1 != Cols2) throw new MatrixDimensionException();
+
+ sol = new double[Rows1 + 1, Cols1 + 1];
+
+ for (i = 0; i <= Rows1; i++)
+ for (j = 0; j <= Cols1; j++) {
+ sol[i, j] = Mat1[i, j] - Mat2[i, j];
+ }
+
+ return sol;
+ }
+
+ ///
+ /// Returns the difference of two matrices with compatible
+ /// dimensions.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First matrix in the subtraction
+ /// Second matrix in the subtraction
+ /// Difference of Mat1 and Mat2 as a Matrix object
+ public static Matrix Subtract(Matrix Mat1, Matrix Mat2) { return new Matrix(Subtract(Mat1.in_Mat, Mat2.in_Mat)); }
+
+ ///
+ /// Returns the difference of two matrices with compatible
+ /// dimensions.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First Matrix object in the subtraction
+ /// Second Matrix object in the subtraction
+ /// Difference of Mat1 and Mat2 as a Matrix object
+ public static Matrix operator -(Matrix Mat1, Matrix Mat2) { return new Matrix(Subtract(Mat1.in_Mat, Mat2.in_Mat)); }
+ #endregion
+
+ #region "Multiply Matrices"
+
+ ///
+ /// Returns the multiplication of two matrices with compatible
+ /// dimensions.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First array in multiplication
+ /// Second array in multiplication
+ /// Mat1 multiplied by Mat2 as an array
+ public static double[,] Multiply(double[,] Mat1, double[,] Mat2) {
+ double[,] sol;
+ int Rows1, Cols1;
+ int Rows2, Cols2;
+ double MulAdd = 0;
+
+ try {
+ Find_R_C(Mat1, out Rows1, out Cols1);
+ Find_R_C(Mat2, out Rows2, out Cols2);
+ }
+ catch {
+ throw new MatrixNullException();
+ }
+ if (Cols1 != Rows2) throw new MatrixDimensionException();
+
+ sol = new double[Rows1 + 1, Cols2 + 1];
+
+ for (int i = 0; i <= Rows1; i++)
+ for (int j = 0; j <= Cols2; j++) {
+ for (int l = 0; l <= Cols1; l++) {
+ MulAdd = MulAdd + Mat1[i, l] * Mat2[l, j];
+ }
+ sol[i, j] = MulAdd;
+ MulAdd = 0;
+ }
+ return sol;
+ }
+
+ ///
+ /// Returns the multiplication of two matrices with compatible
+ /// dimensions OR the cross-product of two vectors.
+ /// In case of an error the error is raised as an exception.
+ ///
+ ///
+ /// First matrix or vector (i.e: dimension [3,1]) object in
+ /// multiplication
+ ///
+ ///
+ /// Second matrix or vector (i.e: dimension [3,1]) object in
+ /// multiplication
+ ///
+ /// Mat1 multiplied by Mat2 as a Matrix object
+ public static Matrix Multiply(Matrix Mat1, Matrix Mat2) {
+ if ((Mat1.Rows == 3) && (Mat2.Rows == 3) &&
+ (Mat1.Columns == 1) && (Mat1.Columns == 1)) { return new Matrix(CrossProduct(Mat1.in_Mat, Mat2.in_Mat)); }
+ else { return new Matrix(Multiply(Mat1.in_Mat, Mat2.in_Mat)); }
+ }
+
+ ///
+ /// Returns the multiplication of two matrices with compatible
+ /// dimensions OR the cross-product of two vectors.
+ /// In case of an error the error is raised as an exception.
+ ///
+ ///
+ /// First matrix or vector (i.e: dimension [3,1]) object in
+ /// multiplication
+ ///
+ ///
+ /// Second matrix or vector (i.e: dimension [3,1]) object in
+ /// multiplication
+ ///
+ /// Mat1 multiplied by Mat2 as a Matrix object
+ public static Matrix operator *(Matrix Mat1, Matrix Mat2) {
+ if ((Mat1.Rows == 3) && (Mat2.Rows == 3) &&
+ (Mat1.Columns == 1) && (Mat1.Columns == 1)) {
+ return new Matrix(CrossProduct(Mat1.in_Mat, Mat2.in_Mat));
+ }
+ else {
+ return new Matrix(Multiply(Mat1.in_Mat, Mat2.in_Mat));
+ }
+ }
+ #endregion
+
+ #region "Determinant of a Matrix"
+ ///
+ /// Returns the determinant of a matrix with [n,n] dimension.
+ /// In case of an error the error is raised as an exception.
+ ///
+ ///
+ /// Array with [n,n] dimension whose determinant is to be found
+ ///
+ /// Determinant of the array
+ public static double Det(double[,] Mat) {
+ int S, k, k1, i, j;
+ double[,] DArray;
+ double save, ArrayK, tmpDet;
+ int Rows, Cols;
+
+ try {
+ DArray = (double[,])Mat.Clone();
+ Find_R_C(Mat, out Rows, out Cols);
+ }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows != Cols) throw new MatrixNotSquare();
+
+ S = Rows;
+ tmpDet = 1;
+
+ for (k = 0; k <= S; k++) {
+ if (DArray[k, k] == 0) {
+ j = k;
+ while ((j < S) && (DArray[k, j] == 0)) j = j + 1;
+ if (DArray[k, j] == 0) return 0;
+ else {
+ for (i = k; i <= S; i++) {
+ save = DArray[i, j];
+ DArray[i, j] = DArray[i, k];
+ DArray[i, k] = save;
+ }
+ }
+ tmpDet = -tmpDet;
+ }
+ ArrayK = DArray[k, k];
+ tmpDet = tmpDet * ArrayK;
+ if (k < S) {
+ k1 = k + 1;
+ for (i = k1; i <= S; i++) {
+ for (j = k1; j <= S; j++)
+ DArray[i, j] = DArray[i, j] - DArray[i, k] * (DArray[k, j] / ArrayK);
+ }
+ }
+ }
+ return tmpDet;
+ }
+
+ ///
+ /// Returns the determinant of a matrix with [n,n] dimension.
+ /// In case of an error the error is raised as an exception.
+ ///
+ ///
+ /// Matrix object with [n,n] dimension whose determinant is to be found
+ ///
+ /// Determinant of the Matrix object
+ public static double Det(Matrix Mat) { return Det(Mat.in_Mat); }
+ #endregion
+
+ #region "Inverse of a Matrix"
+ ///
+ /// Returns the inverse of a matrix with [n,n] dimension
+ /// and whose determinant is not zero.
+ /// In case of an error the error is raised as an exception.
+ ///
+ ///
+ /// Array with [n,n] dimension whose inverse is to be found
+ ///
+ /// Inverse of the array as an array
+ public static double[,] Inverse(double[,] Mat) {
+ double[,] AI, Mat1;
+ double AIN, AF;
+ int Rows, Cols;
+ int LL, LLM, L1, L2, LC, LCA, LCB;
+
+ try {
+ Find_R_C(Mat, out Rows, out Cols);
+ Mat1 = (double[,])Mat.Clone();
+ }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows != Cols) throw new MatrixNotSquare();
+ if (Det(Mat) == 0) throw new MatrixDeterminentZero();
+
+ LL = Rows;
+ LLM = Cols;
+ AI = new double[LL + 1, LL + 1];
+
+ for (L2 = 0; L2 <= LL; L2++) {
+ for (L1 = 0; L1 <= LL; L1++) AI[L1, L2] = 0;
+ AI[L2, L2] = 1;
+ }
+
+ for (LC = 0; LC <= LL; LC++) {
+ if (Math.Abs(Mat1[LC, LC]) < 0.0000000001) {
+ for (LCA = LC + 1; LCA <= LL; LCA++) {
+ if (LCA == LC) continue;
+ if (Math.Abs(Mat1[LC, LCA]) > 0.0000000001) {
+ for (LCB = 0; LCB <= LL; LCB++) {
+ Mat1[LCB, LC] = Mat1[LCB, LC] + Mat1[LCB, LCA];
+ AI[LCB, LC] = AI[LCB, LC] + AI[LCB, LCA];
+ }
+ break;
+ }
+ }
+ }
+ AIN = 1 / Mat1[LC, LC];
+ for (LCA = 0; LCA <= LL; LCA++) {
+ Mat1[LCA, LC] = AIN * Mat1[LCA, LC];
+ AI[LCA, LC] = AIN * AI[LCA, LC];
+ }
+
+ for (LCA = 0; LCA <= LL; LCA++) {
+ if (LCA == LC) continue;
+ AF = Mat1[LC, LCA];
+ for (LCB = 0; LCB <= LL; LCB++) {
+ Mat1[LCB, LCA] = Mat1[LCB, LCA] - AF * Mat1[LCB, LC];
+ AI[LCB, LCA] = AI[LCB, LCA] - AF * AI[LCB, LC];
+ }
+ }
+ }
+ return AI;
+ }
+
+ ///
+ /// Returns the inverse of a matrix with [n,n] dimension
+ /// and whose determinant is not zero.
+ /// In case of an error the error is raised as an exception.
+ ///
+ ///
+ /// Matrix object with [n,n] dimension whose inverse is to be found
+ ///
+ /// Inverse of the matrix as a Matrix object
+ public static Matrix Inverse(Matrix Mat) { return new Matrix(Inverse(Mat.in_Mat)); }
+ #endregion
+
+ #region "Transpose of a Matrix"
+
+ public void Transpose() {
+ in_Mat = Transpose(in_Mat);
+ }
+
+ ///
+ /// Returns the transpose of a matrix.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// Array whose transpose is to be found
+ /// Transpose of the array as an array
+ public static double[,] Transpose(double[,] Mat) {
+ double[,] Tr_Mat;
+ int i, j, Rows, Cols;
+
+ try { Find_R_C(Mat, out Rows, out Cols); }
+ catch { throw new MatrixNullException(); }
+
+ Tr_Mat = new double[Cols + 1, Rows + 1];
+
+ for (i = 0; i <= Rows; i++)
+ for (j = 0; j <= Cols; j++) Tr_Mat[j, i] = Mat[i, j];
+
+ return Tr_Mat;
+ }
+
+ ///
+ /// Returns the transpose of a matrix.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// Matrix object whose transpose is to be found
+ /// Transpose of the Matrix object as a Matrix object
+ public static Matrix Transpose(Matrix Mat) { return new Matrix(Transpose(Mat.in_Mat)); }
+ #endregion
+
+ #region "Singula Value Decomposition of a Matrix"
+ ///
+ /// Evaluates the Singular Value Decomposition of a matrix,
+ /// returns the matrices S, U and V. Such that a given
+ /// Matrix = U x S x V'.
+ /// In case of an error the error is raised as an exception.
+ /// Note: This method is based on the 'Singular Value Decomposition'
+ /// section of Numerical Recipes in C by William H. Press,
+ /// Saul A. Teukolsky, William T. Vetterling and Brian P. Flannery,
+ /// University of Cambridge Press 1992.
+ ///
+ /// Array whose SVD is to be computed
+ /// An array where the S matrix is returned
+ /// An array where the U matrix is returned
+ /// An array where the V matrix is returned
+ public static void SVD(double[,] Mat_, out double[,] S_, out double[,] U_, out double[,] V_) {
+ int Rows, Cols;
+ int m, MP, n, NP;
+ double[] w;
+ double[,] A, v;
+
+ try { Find_R_C(Mat_, out Rows, out Cols); }
+ catch { throw new MatrixNullException(); }
+
+ m = Rows + 1;
+ n = Cols + 1;
+
+ if (m < n) {
+ m = n;
+ MP = NP = n;
+ }
+ else if (m > n) {
+ n = m;
+ NP = MP = m;
+ }
+ else {
+ MP = m;
+ NP = n;
+ }
+
+ A = new double[m + 1, n + 1];
+
+ for (int row = 1; row <= Rows + 1; row++)
+ for (int col = 1; col <= Cols + 1; col++) { A[row, col] = Mat_[row - 1, col - 1]; }
+
+ const int NMAX = 100;
+ v = new double[NP + 1, NP + 1];
+ w = new double[NP + 1];
+
+ int k, l, nm;
+ int flag, i, its, j, jj;
+
+ double[,] U_temp, S_temp, V_temp;
+ double anorm, c, f, g, h, s, scale, x, y, z;
+ double[] rv1 = new double[NMAX];
+
+ l = 0;
+ nm = 0;
+ g = 0.0;
+ scale = 0.0;
+ anorm = 0.0;
+
+ for (i = 1; i <= n; i++) {
+ l = i + 1;
+ rv1[i] = scale * g;
+ g = s = scale = 0.0;
+ if (i <= m) {
+ for (k = i; k <= m; k++) scale += Math.Abs(A[k, i]);
+ if (scale != 0) {
+ for (k = i; k <= m; k++) {
+ A[k, i] /= scale;
+ s += A[k, i] * A[k, i];
+ }
+ f = A[i, i];
+ g = -Sign(Math.Sqrt(s), f);
+ h = f * g - s;
+ A[i, i] = f - g;
+ if (i != n) {
+ for (j = l; j <= n; j++) {
+ for (s = 0, k = i; k <= m; k++) s += A[k, i] * A[k, j];
+ f = s / h;
+ for (k = i; k <= m; k++) A[k, j] += f * A[k, i];
+ }
+ }
+ for (k = i; k <= m; k++) A[k, i] *= scale;
+ }
+ }
+ w[i] = scale * g;
+ g = s = scale = 0.0;
+ if (i <= m && i != n) {
+ for (k = l; k <= n; k++) scale += Math.Abs(A[i, k]);
+ if (scale != 0) {
+ for (k = l; k <= n; k++) {
+ A[i, k] /= scale;
+ s += A[i, k] * A[i, k];
+ }
+ f = A[i, l];
+ g = -Sign(Math.Sqrt(s), f);
+ h = f * g - s;
+ A[i, l] = f - g;
+ for (k = l; k <= n; k++) rv1[k] = A[i, k] / h;
+ if (i != m) {
+ for (j = l; j <= m; j++) {
+ for (s = 0.0, k = l; k <= n; k++) s += A[j, k] * A[i, k];
+ for (k = l; k <= n; k++) A[j, k] += s * rv1[k];
+ }
+ }
+ for (k = l; k <= n; k++) A[i, k] *= scale;
+ }
+ }
+ anorm = Math.Max(anorm, (Math.Abs(w[i]) + Math.Abs(rv1[i])));
+ }
+ for (i = n; i >= 1; i--) {
+ if (i < n) {
+ if (g != 0) {
+ for (j = l; j <= n; j++)
+ v[j, i] = (A[i, j] / A[i, l]) / g;
+ for (j = l; j <= n; j++) {
+ for (s = 0.0, k = l; k <= n; k++) s += A[i, k] * v[k, j];
+ for (k = l; k <= n; k++) v[k, j] += s * v[k, i];
+ }
+ }
+ for (j = l; j <= n; j++) v[i, j] = v[j, i] = 0.0;
+ }
+ v[i, i] = 1.0;
+ g = rv1[i];
+ l = i;
+ }
+ for (i = n; i >= 1; i--) {
+ l = i + 1;
+ g = w[i];
+ if (i < n)
+ for (j = l; j <= n; j++) A[i, j] = 0.0;
+ if (g != 0) {
+ g = 1.0 / g;
+ if (i != n) {
+ for (j = l; j <= n; j++) {
+ for (s = 0.0, k = l; k <= m; k++) s += A[k, i] * A[k, j];
+ f = (s / A[i, i]) * g;
+ for (k = i; k <= m; k++) A[k, j] += f * A[k, i];
+ }
+ }
+ for (j = i; j <= m; j++) A[j, i] *= g;
+ }
+ else {
+ for (j = i; j <= m; j++) A[j, i] = 0.0;
+ }
+ ++A[i, i];
+ }
+ for (k = n; k >= 1; k--) {
+ for (its = 1; its <= 30; its++) {
+ flag = 1;
+ for (l = k; l >= 1; l--) {
+ nm = l - 1;
+ if (Math.Abs(rv1[l]) + anorm == anorm) {
+ flag = 0;
+ break;
+ }
+ if (Math.Abs(w[nm]) + anorm == anorm) break;
+ }
+ if (flag != 0) {
+ c = 0.0;
+ s = 1.0;
+ for (i = l; i <= k; i++) {
+ f = s * rv1[i];
+ if (Math.Abs(f) + anorm != anorm) {
+ g = w[i];
+ h = PYTHAG(f, g);
+ w[i] = h;
+ h = 1.0 / h;
+ c = g * h;
+ s = (-f * h);
+ for (j = 1; j <= m; j++) {
+ y = A[j, nm];
+ z = A[j, i];
+ A[j, nm] = y * c + z * s;
+ A[j, i] = z * c - y * s;
+ }
+ }
+ }
+ }
+ z = w[k];
+ if (l == k) {
+ if (z < 0.0) {
+ w[k] = -z;
+ for (j = 1; j <= n; j++) v[j, k] = (-v[j, k]);
+ }
+ break;
+ }
+ if (its == 30) Console.WriteLine("No convergence in 30 SVDCMP iterations");
+ x = w[l];
+ nm = k - 1;
+ y = w[nm];
+ g = rv1[nm];
+ h = rv1[k];
+ f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
+ g = PYTHAG(f, 1.0);
+ f = ((x - z) * (x + z) + h * ((y / (f + Sign(g, f))) - h)) / x;
+ c = s = 1.0;
+ for (j = l; j <= nm; j++) {
+ i = j + 1;
+ g = rv1[i];
+ y = w[i];
+ h = s * g;
+ g = c * g;
+ z = PYTHAG(f, h);
+ rv1[j] = z;
+ c = f / z;
+ s = h / z;
+ f = x * c + g * s;
+ g = g * c - x * s;
+ h = y * s;
+ y = y * c;
+ for (jj = 1; jj <= n; jj++) {
+ x = v[jj, j];
+ z = v[jj, i];
+ v[jj, j] = x * c + z * s;
+ v[jj, i] = z * c - x * s;
+ }
+ z = PYTHAG(f, h);
+ w[j] = z;
+ if (z != 0) {
+ z = 1.0 / z;
+ c = f * z;
+ s = h * z;
+ }
+ f = (c * g) + (s * y);
+ x = (c * y) - (s * g);
+ for (jj = 1; jj <= m; jj++) {
+ y = A[jj, j];
+ z = A[jj, i];
+ A[jj, j] = y * c + z * s;
+ A[jj, i] = z * c - y * s;
+ }
+ }
+ rv1[l] = 0.0;
+ rv1[k] = f;
+ w[k] = x;
+ }
+ }
+
+ S_temp = new double[NP, NP];
+ V_temp = new double[NP, NP];
+ U_temp = new double[MP, NP];
+
+ for (i = 1; i <= NP; i++) S_temp[i - 1, i - 1] = w[i];
+
+ S_ = S_temp;
+
+ for (i = 1; i <= NP; i++)
+ for (j = 1; j <= NP; j++) V_temp[i - 1, j - 1] = v[i, j];
+
+ V_ = V_temp;
+
+ for (i = 1; i <= MP; i++)
+ for (j = 1; j <= NP; j++) U_temp[i - 1, j - 1] = A[i, j];
+
+ U_ = U_temp;
+ }
+
+ private static double SQR(double a) {
+ return a * a;
+ }
+
+ private static double Sign(double a, double b) {
+ if (b >= 0.0) { return Math.Abs(a); }
+ else { return -Math.Abs(a); }
+ }
+
+ private static double PYTHAG(double a, double b) {
+ double absa, absb;
+
+ absa = Math.Abs(a);
+ absb = Math.Abs(b);
+ if (absa > absb) return absa * Math.Sqrt(1.0 + SQR(absb / absa));
+ else return (absb == 0.0 ? 0.0 : absb * Math.Sqrt(1.0 + SQR(absa / absb)));
+ }
+
+ ///
+ /// Evaluates the Singular Value Decomposition of a matrix,
+ /// returns the matrices S, U and V. Such that a given
+ /// Matrix = U x S x V'.
+ /// In case of an error the error is raised as an exception.
+ /// Note: This method is based on the 'Singular Value Decomposition'
+ /// section of Numerical Recipes in C by William H. Press,
+ /// Saul A. Teukolsky, William T. Vetterling and Brian P. Flannery,
+ /// University of Cambridge Press 1992.
+ ///
+ /// Matrix object whose SVD is to be computed
+ /// A Matrix object where the S matrix is returned
+ /// A Matrix object where the U matrix is returned
+ /// A Matrix object where the V matrix is returned
+ public static void SVD(Matrix Mat, out Matrix S, out Matrix U, out Matrix V) {
+ SVD(Mat.in_Mat, out double[,] s, out double[,] u, out double[,] v);
+ S = new Matrix(s);
+ U = new Matrix(u);
+ V = new Matrix(v);
+ }
+ #endregion
+
+ #region "LU Decomposition of a matrix"
+ ///
+ /// Returns the LU Decomposition of a matrix.
+ /// the output is: lower triangular matrix L, upper
+ /// triangular matrix U, and permutation matrix P so that
+ /// P*X = L*U.
+ /// In case of an error the error is raised as an exception.
+ /// Note: This method is based on the 'LU Decomposition and Its Applications'
+ /// section of Numerical Recipes in C by William H. Press,
+ /// Saul A. Teukolsky, William T. Vetterling and Brian P. Flannery,
+ /// University of Cambridge Press 1992.
+ ///
+ /// Array which will be LU Decomposed
+ /// An array where the lower traingular matrix is returned
+ /// An array where the upper traingular matrix is returned
+ /// An array where the permutation matrix is returned
+ public static void LU(double[,] Mat, out double[,] L, out double[,] U, out double[,] P) {
+ double[,] A;
+ int i, j, k, Rows, Cols;
+
+ try {
+ A = (double[,])Mat.Clone();
+ Find_R_C(Mat, out Rows, out Cols);
+ }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows != Cols) throw new MatrixNotSquare();
+
+ int IMAX = 0, N = Rows;
+ double AAMAX, Sum, Dum, TINY = 1E-20;
+
+ int[] INDX = new int[N + 1];
+ double[] VV = new double[N * 10];
+ double D = 1.0;
+
+ for (i = 0; i <= N; i++) {
+ AAMAX = 0.0;
+ for (j = 0; j <= N; j++)
+ if (Math.Abs(A[i, j]) > AAMAX) AAMAX = Math.Abs(A[i, j]);
+ if (AAMAX == 0.0) throw new MatrixSingularException();
+ VV[i] = 1.0 / AAMAX;
+ }
+ for (j = 0; j <= N; j++) {
+ if (j > 0) {
+ for (i = 0; i <= (j - 1); i++) {
+ Sum = A[i, j];
+ if (i > 0) {
+ for (k = 0; k <= (i - 1); k++)
+ Sum = Sum - A[i, k] * A[k, j];
+ A[i, j] = Sum;
+ }
+ }
+ }
+ AAMAX = 0.0;
+ for (i = j; i <= N; i++) {
+ Sum = A[i, j];
+ if (j > 0) {
+ for (k = 0; k <= (j - 1); k++)
+ Sum = Sum - A[i, k] * A[k, j];
+ A[i, j] = Sum;
+ }
+ Dum = VV[i] * Math.Abs(Sum);
+ if (Dum >= AAMAX) {
+ IMAX = i;
+ AAMAX = Dum;
+ }
+ }
+ if (j != IMAX) {
+ for (k = 0; k <= N; k++) {
+ Dum = A[IMAX, k];
+ A[IMAX, k] = A[j, k];
+ A[j, k] = Dum;
+ }
+ D = -D;
+ VV[IMAX] = VV[j];
+ }
+ INDX[j] = IMAX;
+ if (j != N) {
+ if (A[j, j] == 0.0) A[j, j] = TINY;
+ Dum = 1.0 / A[j, j];
+ for (i = j + 1; i <= N; i++)
+ A[i, j] = A[i, j] * Dum;
+
+ }
+ }
+
+ if (A[N, N] == 0.0) A[N, N] = TINY;
+
+ int count = 0;
+ double[,] l = new double[N + 1, N + 1];
+ double[,] u = new double[N + 1, N + 1];
+
+ for (i = 0; i <= N; i++) {
+ for (j = 0; j <= count; j++) {
+ if (i != 0) l[i, j] = A[i, j];
+ if (i == j) l[i, j] = 1.0;
+ u[N - i, N - j] = A[N - i, N - j];
+ }
+ count++;
+ }
+
+ L = l;
+ U = u;
+
+ P = Identity(N + 1);
+ for (i = 0; i <= N; i++) {
+ SwapRows(P, i, INDX[i]);
+ }
+ }
+
+ private static void SwapRows(double[,] Mat, int Row, int toRow) {
+ int N = Mat.GetUpperBound(0);
+ double[,] dumArray = new double[1, N + 1];
+ for (int i = 0; i <= N; i++) {
+ dumArray[0, i] = Mat[Row, i];
+ Mat[Row, i] = Mat[toRow, i];
+ Mat[toRow, i] = dumArray[0, i];
+ }
+ }
+
+ ///
+ /// Returns the LU Decomposition of a matrix.
+ /// the output is: lower triangular matrix L, upper
+ /// triangular matrix U, and permutation matrix P so that
+ /// P*X = L*U.
+ /// In case of an error the error is raised as an exception.
+ /// Note: This method is based on the 'LU Decomposition and Its Applications'
+ /// section of Numerical Recipes in C by William H. Press,
+ /// Saul A. Teukolsky, William T. Vetterling and Brian P. Flannery,
+ /// University of Cambridge Press 1992.
+ ///
+ /// Matrix object which will be LU Decomposed
+ /// A Matrix object where the lower traingular matrix is returned
+ /// A Matrix object where the upper traingular matrix is returned
+ /// A Matrix object where the permutation matrix is returned
+ public static void LU(Matrix Mat, out Matrix L, out Matrix U, out Matrix P) {
+ LU(Mat.in_Mat, out double[,] l, out double[,] u, out double[,] p);
+ L = new Matrix(l);
+ U = new Matrix(u);
+ P = new Matrix(p);
+ }
+ #endregion
+
+ #region "Solve system of linear equations"
+ ///
+ /// Solves a set of n linear equations A.X = B, and returns
+ /// X, where A is [n,n] and B is [n,1].
+ /// In the same manner if you need to compute: inverse(A).B, it is
+ /// better to use this method instead, as it is much faster.
+ /// In case of an error the error is raised as an exception.
+ /// Note: This method is based on the 'LU Decomposition and Its Applications'
+ /// section of Numerical Recipes in C by William H. Press,
+ /// Saul A. Teukolsky, William T. Vetterling and Brian P. Flannery,
+ /// University of Cambridge Press 1992.
+ ///
+ /// The array 'A' on the left side of the equations A.X = B
+ /// The array 'B' on the right side of the equations A.X = B
+ /// Array 'X' in the system of equations A.X = B
+ public static double[,] SolveLinear(double[,] MatA, double[,] MatB) {
+ double[,] A;
+ double[,] B;
+ double SUM;
+ int i, ii, j, k, ll, Rows, Cols;
+
+ #region "LU Decompose"
+ try {
+ A = (double[,])MatA.Clone();
+ B = (double[,])MatB.Clone();
+ Find_R_C(A, out Rows, out Cols);
+ }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows != Cols) throw new MatrixNotSquare();
+ if ((B.GetUpperBound(0) != Rows) || (B.GetUpperBound(1) != 0))
+ throw new MatrixDimensionException();
+
+ int IMAX = 0, N = Rows;
+ double AAMAX, Sum, Dum, TINY = 1E-20;
+
+ int[] INDX = new int[N + 1];
+ double[] VV = new double[N * 10];
+ double D = 1.0;
+
+ for (i = 0; i <= N; i++) {
+ AAMAX = 0.0;
+ for (j = 0; j <= N; j++)
+ if (Math.Abs(A[i, j]) > AAMAX) AAMAX = Math.Abs(A[i, j]);
+ if (AAMAX == 0.0) throw new MatrixSingularException();
+ VV[i] = 1.0 / AAMAX;
+ }
+ for (j = 0; j <= N; j++) {
+ if (j > 0) {
+ for (i = 0; i <= (j - 1); i++) {
+ Sum = A[i, j];
+ if (i > 0) {
+ for (k = 0; k <= (i - 1); k++)
+ Sum = Sum - A[i, k] * A[k, j];
+ A[i, j] = Sum;
+ }
+ }
+ }
+ AAMAX = 0.0;
+ for (i = j; i <= N; i++) {
+ Sum = A[i, j];
+ if (j > 0) {
+ for (k = 0; k <= (j - 1); k++)
+ Sum = Sum - A[i, k] * A[k, j];
+ A[i, j] = Sum;
+ }
+ Dum = VV[i] * Math.Abs(Sum);
+ if (Dum >= AAMAX) {
+ IMAX = i;
+ AAMAX = Dum;
+ }
+ }
+ if (j != IMAX) {
+ for (k = 0; k <= N; k++) {
+ Dum = A[IMAX, k];
+ A[IMAX, k] = A[j, k];
+ A[j, k] = Dum;
+ }
+ D = -D;
+ VV[IMAX] = VV[j];
+ }
+ INDX[j] = IMAX;
+ if (j != N) {
+ if (A[j, j] == 0.0) A[j, j] = TINY;
+ Dum = 1.0 / A[j, j];
+ for (i = j + 1; i <= N; i++)
+ A[i, j] = A[i, j] * Dum;
+
+ }
+ }
+ if (A[N, N] == 0.0) A[N, N] = TINY;
+ #endregion
+
+ ii = -1;
+ for (i = 0; i <= N; i++) {
+ ll = INDX[i];
+ SUM = B[ll, 0];
+ B[ll, 0] = B[i, 0];
+ if (ii != -1) {
+ for (j = ii; j <= i - 1; j++) SUM = SUM - A[i, j] * B[j, 0];
+ }
+ else if (SUM != 0) ii = i;
+ B[i, 0] = SUM;
+ }
+ for (i = N; i >= 0; i--) {
+ SUM = B[i, 0];
+ if (i < N) {
+ for (j = i + 1; j <= N; j++) SUM = SUM - A[i, j] * B[j, 0];
+ }
+ B[i, 0] = SUM / A[i, i];
+ }
+ return B;
+ }
+
+ ///
+ /// Solves a set of n linear equations A.X = B, and returns
+ /// X, where A is [n,n] and B is [n,1].
+ /// In the same manner if you need to compute: inverse(A).B, it is
+ /// better to use this method instead, as it is much faster.
+ /// In case of an error the error is raised as an exception.
+ /// Note: This method is based on the 'LU Decomposition and Its Applications'
+ /// section of Numerical Recipes in C by William H. Press,
+ /// Saul A. Teukolsky, William T. Vetterling and Brian P. Flannery,
+ /// University of Cambridge Press 1992.
+ ///
+ /// Matrix object 'A' on the left side of the equations A.X = B
+ /// Matrix object 'B' on the right side of the equations A.X = B
+ /// Matrix object 'X' in the system of equations A.X = B
+ public static Matrix SolveLinear(Matrix MatA, Matrix MatB) { return new Matrix(Matrix.SolveLinear(MatA.in_Mat, MatB.in_Mat)); }
+ #endregion
+
+ #region "Rank of a matrix"
+ ///
+ /// Returns the rank of a matrix.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// An array whose rank is to be found
+ /// The rank of the array
+ public static int Rank(double[,] Mat) {
+ int r = 0;
+ try {
+ Find_R_C(Mat, out int Rows, out int Cols);
+ }
+ catch { throw new MatrixNullException(); }
+ double EPS = 2.2204E-16;
+ SVD(Mat, out double[,] S, out double[,] U, out double[,] V);
+
+ for (int i = 0; i <= S.GetUpperBound(0); i++) { if (Math.Abs(S[i, i]) > EPS) r++; }
+
+ return r;
+ }
+
+ ///
+ /// Returns the rank of a matrix.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// a Matrix object whose rank is to be found
+ /// The rank of the Matrix object
+ public static int Rank(Matrix Mat) { return Rank(Mat.in_Mat); }
+ #endregion
+
+ #region "Pseudoinverse of a matrix"
+ ///
+ /// Returns the pseudoinverse of a matrix, such that
+ /// X = PINV(A) produces a matrix 'X' of the same dimensions
+ /// as A' so that A*X*A = A, X*A*X = X.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// An array whose pseudoinverse is to be found
+ /// The pseudoinverse of the array as an array
+ public static double[,] PINV(double[,] Mat) {
+ double[,] Matrix;
+ int i, m, n, j, l;
+ double[,] S, Part_I, Part_II;
+ double EPS, MulAdd, Tol, Largest_Item = 0;
+
+ try {
+ Matrix = (double[,])Mat.Clone();
+ Find_R_C(Mat, out m, out n);
+ }
+ catch { throw new MatrixNullException(); }
+
+ SVD(Mat, out double[,] svdS, out double[,] svdU, out double[,] svdV);
+
+ EPS = 2.2204E-16;
+ m++;
+ n++;
+
+ Part_I = new double[m, n];
+ Part_II = new double[m, n];
+ S = new Double[n, n];
+
+ MulAdd = 0;
+ for (i = 0; i <= svdS.GetUpperBound(0); i++) {
+ if (i == 0) Largest_Item = svdS[0, 0];
+ if (Largest_Item < svdS[i, i]) Largest_Item = svdS[i, i];
+ }
+
+ if (m > n) Tol = m * Largest_Item * EPS;
+ else Tol = n * Largest_Item * EPS;
+
+ for (i = 0; i < n; i++) S[i, i] = svdS[i, i];
+
+ for (i = 0; i < m; i++) {
+ for (j = 0; j < n; j++) {
+ for (l = 0; l < n; l++) {
+ if (S[l, j] > Tol) MulAdd += svdU[i, l] * (1 / S[l, j]);
+ }
+ Part_I[i, j] = MulAdd;
+ MulAdd = 0;
+ }
+ }
+
+ for (i = 0; i < m; i++) {
+ for (j = 0; j < n; j++) {
+ for (l = 0; l < n; l++) {
+ MulAdd += Part_I[i, l] * svdV[j, l];
+ }
+ Part_II[i, j] = MulAdd;
+ MulAdd = 0;
+ }
+ }
+ return Transpose(Part_II);
+ }
+
+ ///
+ /// Returns the pseudoinverse of a matrix, such that
+ /// X = PINV(A) produces a matrix 'X' of the same dimensions
+ /// as A' so that A*X*A = A, X*A*X = X.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// a Matrix object whose pseudoinverse is to be found
+ /// The pseudoinverse of the Matrix object as a Matrix Object
+ public static Matrix PINV(Matrix Mat) { return new Matrix(PINV(Mat.in_Mat)); }
+ #endregion
+
+ #region "Eigen Values and Vactors of Symmetric Matrix"
+ ///
+ /// Returns the Eigenvalues and Eigenvectors of a real symmetric
+ /// matrix, which is of dimensions [n,n].
+ /// In case of an error the error is raised as an exception.
+ /// Note: This method is based on the 'Eigenvalues and Eigenvectors of a TridiagonalMatrix'
+ /// section of Numerical Recipes in C by William H. Press,
+ /// Saul A. Teukolsky, William T. Vetterling and Brian P. Flannery,
+ /// University of Cambridge Press 1992.
+ ///
+ ///
+ /// The array whose Eigenvalues and Eigenvectors are to be found
+ ///
+ /// An array where the eigenvalues are returned
+ /// An array where the eigenvectors are returned
+ public static void Eigen(double[,] Mat, out double[,] d, out double[,] v) {
+
+ double[,] a;
+ int Rows, Cols;
+ try {
+ Find_R_C(Mat, out Rows, out Cols);
+ a = (double[,])Mat.Clone();
+ }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows != Cols) throw new MatrixNotSquare();
+
+ int j, iq, ip, i, n, nrot;
+ double tresh, theta, tau, t, sm, s, h, g, c;
+ double[] b, z;
+
+ n = Rows;
+ d = new double[n + 1, 1];
+ v = new double[n + 1, n + 1];
+
+ b = new double[n + 1];
+ z = new double[n + 1];
+ for (ip = 0; ip <= n; ip++) {
+ for (iq = 0; iq <= n; iq++) v[ip, iq] = 0.0;
+ v[ip, ip] = 1.0;
+ }
+ for (ip = 0; ip <= n; ip++) {
+ b[ip] = d[ip, 0] = a[ip, ip];
+ z[ip] = 0.0;
+ }
+
+ nrot = 0;
+ for (i = 0; i <= 50; i++) {
+ sm = 0.0;
+ for (ip = 0; ip <= n - 1; ip++) {
+ for (iq = ip + 1; iq <= n; iq++)
+ sm += Math.Abs(a[ip, iq]);
+ }
+ if (sm == 0.0) {
+ return;
+ }
+ if (i < 4)
+ tresh = 0.2 * sm / (n * n);
+ else
+ tresh = 0.0;
+ for (ip = 0; ip <= n - 1; ip++) {
+ for (iq = ip + 1; iq <= n; iq++) {
+ g = 100.0 * Math.Abs(a[ip, iq]);
+ if (i > 4 && (double)(Math.Abs(d[ip, 0]) + g) == (double)Math.Abs(d[ip, 0])
+ && (double)(Math.Abs(d[iq, 0]) + g) == (double)Math.Abs(d[iq, 0]))
+ a[ip, iq] = 0.0;
+ else if (Math.Abs(a[ip, iq]) > tresh) {
+ h = d[iq, 0] - d[ip, 0];
+ if ((double)(Math.Abs(h) + g) == (double)Math.Abs(h))
+ t = (a[ip, iq]) / h;
+ else {
+ theta = 0.5 * h / (a[ip, iq]);
+ t = 1.0 / (Math.Abs(theta) + Math.Sqrt(1.0 + theta * theta));
+ if (theta < 0.0) t = -t;
+ }
+ c = 1.0 / Math.Sqrt(1 + t * t);
+ s = t * c;
+ tau = s / (1.0 + c);
+ h = t * a[ip, iq];
+ z[ip] -= h;
+ z[iq] += h;
+ d[ip, 0] -= h;
+ d[iq, 0] += h;
+ a[ip, iq] = 0.0;
+ for (j = 0; j <= ip - 1; j++) {
+ ROT(g, h, s, tau, a, j, ip, j, iq);
+ }
+ for (j = ip + 1; j <= iq - 1; j++) {
+ ROT(g, h, s, tau, a, ip, j, j, iq);
+ }
+ for (j = iq + 1; j <= n; j++) {
+ ROT(g, h, s, tau, a, ip, j, iq, j);
+ }
+ for (j = 0; j <= n; j++) {
+ ROT(g, h, s, tau, v, j, ip, j, iq);
+ }
+ ++(nrot);
+ }
+ }
+ }
+ for (ip = 0; ip <= n; ip++) {
+ b[ip] += z[ip];
+ d[ip, 0] = b[ip];
+ z[ip] = 0.0;
+ }
+ }
+ Console.WriteLine("Too many iterations in routine jacobi");
+ }
+
+ private static void ROT(double g, double h, double s, double tau,
+ double[,] a, int i, int j, int k, int l) {
+ g = a[i, j]; h = a[k, l];
+ a[i, j] = g - s * (h + g * tau);
+ a[k, l] = h + s * (g - h * tau);
+ }
+
+ ///
+ /// Returns the Eigenvalues and Eigenvectors of a real symmetric
+ /// matrix, which is of dimensions [n,n]. In case of an error the
+ /// error is raised as an exception.
+ /// Note: This method is based on the 'Eigenvalues and Eigenvectors of a TridiagonalMatrix'
+ /// section of Numerical Recipes in C by William H. Press,
+ /// Saul A. Teukolsky, William T. Vetterling and Brian P. Flannery,
+ /// University of Cambridge Press 1992.
+ ///
+ ///
+ /// The Matrix object whose Eigenvalues and Eigenvectors are to be found
+ ///
+ /// A Matrix object where the eigenvalues are returned
+ /// A Matrix object where the eigenvectors are returned
+ public static void Eigen(Matrix Mat, out Matrix d, out Matrix v) {
+ Eigen(Mat.in_Mat, out double[,] D, out double[,] V);
+ d = new Matrix(D);
+ v = new Matrix(V);
+ }
+ #endregion
+
+ #region "Multiply a matrix or a vector with a scalar quantity"
+ ///
+ /// Returns the multiplication of a matrix or a vector (i.e
+ /// dimension [3,1]) with a scalar quantity.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The scalar value to multiply the array
+ /// Array which is to be multiplied by a scalar
+ /// The multiplication of the scalar and the array as an array
+ public static double[,] ScalarMultiply(double Value, double[,] Mat) {
+ int i, j, Rows, Cols;
+ double[,] sol;
+
+ try { Find_R_C(Mat, out Rows, out Cols); }
+ catch { throw new MatrixNullException(); }
+ sol = new double[Rows + 1, Cols + 1];
+
+ for (i = 0; i <= Rows; i++)
+ for (j = 0; j <= Cols; j++)
+ sol[i, j] = Mat[i, j] * Value;
+
+ return sol;
+ }
+
+ ///
+ /// Returns the multiplication of a matrix or a vector (i.e
+ /// dimension [3,1]) with a scalar quantity.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The scalar value to multiply the array
+ /// Matrix which is to be multiplied by a scalar
+ /// The multiplication of the scalar and the array as an array
+ public static Matrix ScalarMultiply(double Value, Matrix Mat) { return new Matrix(ScalarMultiply(Value, Mat.in_Mat)); }
+
+ ///
+ /// Returns the multiplication of a matrix or a vector (i.e
+ /// dimension [3,1]) with a scalar quantity.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// Matrix object which is to be multiplied by a scalar
+ /// The scalar value to multiply the Matrix object
+ ///
+ /// The multiplication of the scalar and the Matrix object as a
+ /// Matrix object
+ ///
+ public static Matrix operator *(Matrix Mat, double Value) { return new Matrix(ScalarMultiply(Value, Mat.in_Mat)); }
+
+ ///
+ /// Returns the multiplication of a matrix or a vector (i.e
+ /// dimension [3,1]) with a scalar quantity.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The scalar value to multiply the Matrix object
+ /// Matrix object which is to be multiplied by a scalar
+ ///
+ /// The multiplication of the scalar and the Matrix object as a
+ /// Matrix object
+ ///
+ public static Matrix operator *(double Value, Matrix Mat) { return new Matrix(ScalarMultiply(Value, Mat.in_Mat)); }
+ #endregion
+
+ #region "Divide a matrix or a vector with a scalar quantity"
+ ///
+ /// Returns the division of a matrix or a vector (i.e
+ /// dimension [3,1]) by a scalar quantity.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The scalar value to divide the array with
+ /// Array which is to be divided by a scalar
+ /// The division of the array and the scalar as an array
+ public static double[,] ScalarDivide(double Value, double[,] Mat) {
+ int i, j, Rows, Cols;
+ double[,] sol;
+
+ try { Find_R_C(Mat, out Rows, out Cols); }
+ catch { throw new MatrixNullException(); }
+
+ sol = new double[Rows + 1, Cols + 1];
+
+ for (i = 0; i <= Rows; i++)
+ for (j = 0; j <= Cols; j++)
+ sol[i, j] = Mat[i, j] / Value;
+
+ return sol;
+ }
+
+ ///
+ /// Returns the division of a matrix or a vector (i.e
+ /// dimension [3,1]) by a scalar quantity.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The scalar value to divide the array with
+ /// Matrix which is to be divided by a scalar
+ /// The division of the array and the scalar as an array
+ public static Matrix ScalarDivide(double Value, Matrix Mat) { return new Matrix(ScalarDivide(Value, Mat.in_Mat)); }
+
+ ///
+ /// Returns the division of a matrix or a vector (i.e
+ /// dimension [3,1]) by a scalar quantity.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The scalar value to divide the Matrix object with
+ /// Matrix object which is to be divided by a scalar
+ ///
+ /// The division of the Matrix object and the scalar as a Matrix object
+ ///
+ public static Matrix operator /(Matrix Mat, double Value) { return new Matrix(ScalarDivide(Value, Mat.in_Mat)); }
+ #endregion
+
+ #region "Vectors Cross Product"
+ ///
+ /// Returns the cross product of two vectors whose
+ /// dimensions should be [3] or [3,1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First vector array (dimension [3]) in the cross product
+ /// Second vector array (dimension [3]) in the cross product
+ /// Cross product of V1 and V2 as an array (dimension [3])
+ public static double[] CrossProduct(double[] V1, double[] V2) {
+ double i, j, k;
+ double[] sol = new double[2];
+ int Rows1;
+ int Rows2;
+
+ try {
+ Find_R_C(V1, out Rows1);
+ Find_R_C(V2, out Rows2);
+ }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows1 != 2) throw new VectorDimensionException();
+
+ if (Rows2 != 2) throw new VectorDimensionException();
+
+ i = V1[1] * V2[2] - V1[2] * V2[1];
+ j = V1[2] * V2[0] - V1[0] * V2[2];
+ k = V1[0] * V2[1] - V1[1] * V2[0];
+
+ sol[0] = i; sol[1] = j; sol[2] = k;
+
+ return sol;
+ }
+
+ ///
+ /// Returns the cross product of two vectors whose
+ /// dimensions should be [3] or [3x1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First vector array (dimensions [3,1]) in the cross product
+ /// Second vector array (dimensions [3,1]) in the cross product
+ /// Cross product of V1 and V2 as an array (dimension [3,1])
+ public static double[,] CrossProduct(double[,] V1, double[,] V2) {
+ double i, j, k;
+ double[,] sol = new double[3, 1];
+ int Rows1, Cols1;
+ int Rows2, Cols2;
+
+ try {
+ Find_R_C(V1, out Rows1, out Cols1);
+ Find_R_C(V2, out Rows2, out Cols2);
+ }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows1 != 2 || Cols1 != 0) throw new VectorDimensionException();
+
+ if (Rows2 != 2 || Cols2 != 0) throw new VectorDimensionException();
+
+ i = V1[1, 0] * V2[2, 0] - V1[2, 0] * V2[1, 0];
+ j = V1[2, 0] * V2[0, 0] - V1[0, 0] * V2[2, 0];
+ k = V1[0, 0] * V2[1, 0] - V1[1, 0] * V2[0, 0];
+
+ sol[0, 0] = i; sol[1, 0] = j; sol[2, 0] = k;
+
+ return sol;
+ }
+
+ ///
+ /// Returns the cross product of two vectors whose
+ /// dimensions should be [3] or [3x1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First Matrix (dimensions [3,1]) in the cross product
+ /// Second Matrix (dimensions [3,1]) in the cross product
+ /// Cross product of V1 and V2 as a matrix (dimension [3,1])
+ public static Matrix CrossProduct(Matrix V1, Matrix V2) { return (new Matrix((CrossProduct(V1.in_Mat, V2.in_Mat)))); }
+ #endregion
+
+ #region "Vectors Dot Product"
+ ///
+ /// Returns the dot product of two vectors whose
+ /// dimensions should be [3] or [3,1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First vector array (dimension [3]) in the dot product
+ /// Second vector array (dimension [3]) in the dot product
+ /// Dot product of V1 and V2
+ public static double DotProduct(double[] V1, double[] V2) {
+ int Rows1;
+ int Rows2;
+
+ try {
+ Find_R_C(V1, out Rows1);
+ Find_R_C(V2, out Rows2);
+ }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows1 != 2) throw new VectorDimensionException();
+
+ if (Rows2 != 2) throw new VectorDimensionException();
+
+ return (V1[0] * V2[0] + V1[1] * V2[1] + V1[2] * V2[2]);
+ }
+
+ ///
+ /// Returns the dot product of two vectors whose
+ /// dimensions should be [3] or [3,1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First vector array (dimension [3,1]) in the dot product
+ /// Second vector array (dimension [3,1]) in the dot product
+ /// Dot product of V1 and V2
+ public static double DotProduct(double[,] V1, double[,] V2) {
+ int Rows1, Cols1;
+ int Rows2, Cols2;
+
+ try {
+ Find_R_C(V1, out Rows1, out Cols1);
+ Find_R_C(V2, out Rows2, out Cols2);
+ }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows1 != 2 || Cols1 != 0) throw new VectorDimensionException();
+
+ if (Rows2 != 2 || Cols2 != 0) throw new VectorDimensionException();
+
+ return (V1[0, 0] * V2[0, 0] + V1[1, 0] * V2[1, 0] + V1[2, 0] * V2[2, 0]);
+ }
+
+ ///
+ /// Returns the dot product of two vectors whose
+ /// dimensions should be [3] or [3,1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First Matrix object (dimension [3,1]) in the dot product
+ /// Second Matrix object (dimension [3,1]) in the dot product
+ /// Dot product of V1 and V2
+ public static double DotProduct(Matrix V1, Matrix V2) { return (DotProduct(V1.in_Mat, V2.in_Mat)); }
+ #endregion
+
+ #region "Magnitude of a Vector"
+ ///
+ /// Returns the magnitude of a vector whose dimension is [3] or [3,1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The vector array (dimension [3]) whose magnitude is to be found
+ /// The magnitude of the vector array
+ public static double VectorMagnitude(double[] V) {
+ int Rows;
+
+ try { Find_R_C(V, out Rows); }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows != 2) throw new VectorDimensionException();
+
+ return Math.Sqrt(V[0] * V[0] + V[1] * V[1] + V[2] * V[2]);
+ }
+
+ ///
+ /// Returns the magnitude of a vector whose dimension is [3] or [3,1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The vector array (dimension [3,1]) whose magnitude is to be found
+ /// The magnitude of the vector array
+ public static double VectorMagnitude(double[,] V) {
+ int Rows, Cols;
+
+ try { Find_R_C(V, out Rows, out Cols); }
+ catch { throw new MatrixNullException(); }
+
+ if (Rows != 2 || Cols != 0) throw new VectorDimensionException();
+
+ return Math.Sqrt(V[0, 0] * V[0, 0] + V[1, 0] * V[1, 0] + V[2, 0] * V[2, 0]);
+ }
+
+ ///
+ /// Returns the magnitude of a vector whose dimension is [3] or [3,1].
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// Matrix object (dimension [3,1]) whose magnitude is to be found
+ /// The magnitude of the Matrix object
+ public static double VectorMagnitude(Matrix V) { return (VectorMagnitude(V.in_Mat)); }
+ #endregion
+
+ #region "Two Matrices are equal or not"
+ ///
+ /// Checks if two Arrays of equal dimensions are equal or not.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First array in equality check
+ /// Second array in equality check
+ /// If two matrices are equal or not
+ public static bool IsEqual(double[,] Mat1, double[,] Mat2) {
+ double eps = 1E-14;
+ int Rows1, Cols1;
+ int Rows2, Cols2;
+
+ //Find The dimensions !!
+ try {
+ Find_R_C(Mat1, out Rows1, out Cols1);
+ Find_R_C(Mat2, out Rows2, out Cols2);
+ }
+ catch {
+ throw new MatrixNullException();
+ }
+ if (Rows1 != Rows2 || Cols1 != Cols2) throw new MatrixDimensionException();
+
+ for (int i = 0; i <= Rows1; i++) {
+ for (int j = 0; j <= Cols1; j++) {
+ if (Math.Abs(Mat1[i, j] - Mat2[i, j]) > eps) return false;
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Checks if two matrices of equal dimensions are equal or not.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First Matrix in equality check
+ /// Second Matrix in equality check
+ /// If two matrices are equal or not
+ public static bool IsEqual(Matrix Mat1, Matrix Mat2) { return IsEqual(Mat1.in_Mat, Mat2.in_Mat); }
+
+ ///
+ /// Checks if two matrices of equal dimensions are equal or not.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First Matrix object in equality check
+ /// Second Matrix object in equality check
+ /// If two matrices are equal or not
+ public static bool operator ==(Matrix Mat1, Matrix Mat2) { return IsEqual(Mat1.in_Mat, Mat2.in_Mat); }
+
+ ///
+ /// Checks if two matrices of equal dimensions are not equal.
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// First Matrix object in equality check
+ /// Second Matrix object in equality check
+ /// If two matrices are not equal
+ public static bool operator !=(Matrix Mat1, Matrix Mat2) { return (!IsEqual(Mat1.in_Mat, Mat2.in_Mat)); }
+
+ ///
+ /// Tests whether the specified object is a MatrixLibrary.Matrix
+ /// object and is identical to this MatrixLibrary.Matrix object.
+ ///
+ /// The object to compare with the current object
+ /// This method returns true if obj is the specified Matrix object identical to this Matrix object; otherwise, false.
+ public override bool Equals(Object obj) {
+ try { return (bool)(this == (Matrix)obj); }
+ catch { return false; }
+ }
+ #endregion
+
+ #region "Print Matrix"
+ ///
+ /// Returns a matrix as a string, so it can be viewed
+ /// in a multi-text textbox or in a richtextBox (preferred).
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The array to be viewed
+ /// The string view of the array
+ public static string PrintMat(double[,] Mat) {
+ int N_Rows, N_Columns, k, i, j, m;
+ string StrElem;
+ int StrLen; int[] Greatest;
+ string LarString, OptiString, sol;
+
+ //Find The dimensions !!
+ try { Find_R_C(Mat, out N_Rows, out N_Columns); }
+ catch {
+ throw new MatrixNullException();
+ }
+
+ sol = "";
+ LarString = "";
+ OptiString = "";
+ Greatest = new int[N_Columns + 1];
+
+ for (i = 0; i <= N_Rows; i++) {
+ for (j = 0; j <= N_Columns; j++) {
+ if (i == 0) {
+ Greatest[j] = 0;
+ for (m = 0; m <= N_Rows; m++) {
+ StrElem = Mat[m, j].ToString("0.0000");
+ StrLen = StrElem.Length;
+ if (Greatest[j] < StrLen) {
+ Greatest[j] = StrLen;
+ LarString = StrElem;
+ }
+ }
+ if (LarString.StartsWith("-")) Greatest[j] = Greatest[j];
+ }
+ StrElem = Mat[i, j].ToString("0.0000");
+ if (StrElem.StartsWith("-")) {
+ StrLen = StrElem.Length;
+ if (Greatest[j] >= StrLen) {
+ for (k = 1; k <= (Greatest[j] - StrLen); k++) OptiString += " ";
+ OptiString += " ";
+ }
+ }
+ else {
+ StrLen = StrElem.Length;
+ if (Greatest[j] > StrLen) {
+ for (k = 1; k <= (Greatest[j] - StrLen); k++) {
+ OptiString += " ";
+ }
+ }
+ }
+ OptiString += " " + (Mat[i, j].ToString("0.0000"));
+ }
+
+ if (i != N_Rows) {
+ sol += OptiString + "\n";
+ OptiString = "";
+ }
+ sol += OptiString;
+ OptiString = "";
+ }
+ return sol;
+ }
+
+ ///
+ /// Returns a matrix as a string, so it can be viewed
+ /// in a multi-text textbox or in a richtextBox (preferred).
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The Matrix object to be viewed
+ /// The string view of the Matrix object
+ public static string PrintMat(Matrix Mat) { return (PrintMat(Mat.in_Mat)); }
+
+ ///
+ /// Returns the matrix as a string, so it can be viewed
+ /// in a multi-text textbox or in a richtextBox (preferred).
+ /// In case of an error the error is raised as an exception.
+ ///
+ /// The string view of the Matrix object
+ public override string ToString() { return (PrintMat(this.in_Mat)); }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/SharpGL/OpenGL.cs b/src/SharpGL/OpenGL.cs
index cf64b72..53503f4 100644
--- a/src/SharpGL/OpenGL.cs
+++ b/src/SharpGL/OpenGL.cs
@@ -4,6 +4,7 @@ using System.ComponentModel;
using System.Runtime.InteropServices;
using SharpGL.RenderContextProviders;
using SharpGL.Version;
+using System.Numerics;
namespace SharpGL
{
@@ -3978,6 +3979,16 @@ namespace SharpGL
PostGLCall();
}
+ ///
+ /// Multiply the current matrix with the specified matrix.
+ ///
+ /// Points to 16 consecutive values that are used as the elements of a 4x4 column-major matrix.
+ public void MultMatrix(Matrix m) {
+ PreGLCall();
+ glMultMatrixd(m.As1DArray);
+ PostGLCall();
+ }
+
///
/// Multiply the current matrix with the specified matrix.
///
@@ -6003,12 +6014,22 @@ namespace SharpGL
return result;
}
- ///
+ ///
/// Set the current vertex (must be called between 'Begin' and 'End').
///
- /// X Value.
- /// Y Value.
- public void Vertex(double x, double y)
+ /// The to the vertex pointing vector.
+ public void Vertex(Vector2 vertex) {
+ PreGLCall();
+ glVertex2d(vertex.X, vertex.Y);
+ PostGLCall();
+ }
+
+ ///
+ /// Set the current vertex (must be called between 'Begin' and 'End').
+ ///
+ /// X Value.
+ /// Y Value.
+ public void Vertex(double x, double y)
{
PreGLCall();
glVertex2d(x, y);
diff --git a/src/SharpGL/OpenGLExtensions.cs b/src/SharpGL/OpenGLExtensions.cs
index 71e2593..4c251e6 100644
--- a/src/SharpGL/OpenGLExtensions.cs
+++ b/src/SharpGL/OpenGLExtensions.cs
@@ -38,8 +38,7 @@ namespace SharpGL
string name = delegateType.Name;
// ftlPhysicsGuy - Better way
- Delegate del = null;
- if (extensionFunctions.TryGetValue(name, out del) == false)
+ if (extensionFunctions.TryGetValue(name, out Delegate del) == false)
{
IntPtr proc = Win32.wglGetProcAddress(name);
if (proc == IntPtr.Zero)
diff --git a/src/canvas.cs b/src/canvas.cs
deleted file mode 100644
index bc05418..0000000
--- a/src/canvas.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using System;
-using System.Windows.Forms;
-using SharpGL.Enumerations;
-using SharpGL.Version;
-using SharpGL;
-using System.ComponentModel;
-
-namespace JuicyGraphics {
- class canvas : Control, ISupportInitialize {
-
- protected OpenGL GL = new OpenGL();
-
- public canvas() {
- SetStyle(ControlStyles.AllPaintingInWmPaint, true);
- SetStyle(ControlStyles.UserPaint, true);
- InitializeOpenGL();
- }
-
- protected void InitializeOpenGL() {
- GL.Create(OpenGLVersion.OpenGL4_3, RenderContextType.NativeWindow, Width, Height, 32, this.Handle);
- GL.ShadeModel(OpenGL.GL_SMOOTH);
- GL.ClearDepth(1.0f);
- GL.Enable(OpenGL.GL_DEPTH_TEST);
- GL.DepthFunc(OpenGL.GL_LEQUAL);
- GL.Hint(OpenGL.GL_PERSPECTIVE_CORRECTION_HINT, OpenGL.GL_NICEST);
- GL.Viewport(0, 0, Width, Height);
- }
-
- bool renderingForDesigner() {
- if (this == null)
- return false;
- if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
- return true;
- Control p = this.Parent;
- while (p != null) {
- if (p.GetType().FullName.Contains(".DesignerFrame"))
- return true;
- p = p.Parent;
- }
- return false;
- }
-
- protected override void OnPaintBackground(PaintEventArgs e) {
- if (renderingForDesigner()) { base.OnPaintBackground(e); }
- return;
- }
-
- protected override void OnPaint(PaintEventArgs e) {
- if (renderingForDesigner()) {
- SetStyle(ControlStyles.AllPaintingInWmPaint, true);
- SetStyle(ControlStyles.UserPaint, true);
- InitializeOpenGL();
- }
- GL.MakeCurrent();
- GL.ClearColor(0f, 0.3f, 0.7f, 1f);
- GL.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
-
- GL.Begin(BeginMode.Triangles);
- GL.Color(0.8, 0.1, 0.1);
- GL.Vertex(1.0, 1.0);
- GL.Vertex(-1.0, -1.0); GL.Vertex(-1.0, 1.0);
- GL.End();
- GL.Flush();
-
- var handleDeviceContext = e.Graphics.GetHdc();
- GL.Blit(handleDeviceContext);
- e.Graphics.ReleaseHdc(handleDeviceContext);
- }
-
- protected override void OnSizeChanged(EventArgs e) {
- if (GL.RenderContextProvider == null)
- return;
- GL.SetDimensions(Width, Height);
- GL.Viewport(0, 0, Width, Height);
- Invalidate();
- }
-
- public void BeginInit() { }
-
- public void EndInit() {
- InitializeOpenGL();
- OnSizeChanged(null);
- }
- }
-}
\ No newline at end of file