using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace Cone
{
    class clCone
    {
        private byte[,] brgPixelsB;
        private byte[,] brgPixelsG;
        private byte[,] brgPixelsR;
        private byte[,] brgPixelsL;
        private int[,] virgPoints;
        private int[] virgPointsL;
        private int[] viLength;
        private int viI;
        private int viJ;


        private int pointMittingX = 0;
        private int viLengthP = 0;
        private double koefX = 0;
        private double koefX1 = 0;
        private double koefY = 0;
        private int viFromX = 0;
        private int viFromY = 0;
        private int viTo1 = 0;


        private int radius;
        private Form1 myForm;
        private bool fBlock = false;


        private int viWidth = 0;
        private int viHeight = 0;
        public Graphics graphWork = null;

        public Graphics graph = null;
        private byte[] bmpBytesSource;
        private byte[] bmpBytesFore;

        //Исходная в половину 
        private static Bitmap bmpStart = null;
        private Bitmap bitmapWorkFore { get; set; }
        private Bitmap bitmapWork { get; set; }


        public clCone(Form1 form1)
        {
            // TODO: Complete member initialization
            myForm = form1;
        }

        internal void vNewSize()
        {

            if (fBlock) return;
            fBlock = true;


            //Адрес картинки            
            string s = myForm.srgFiles[myForm.viImage];
            //Картинка из памяти 
            Bitmap bmpTemp = new Bitmap(s);
            viWidth = bmpTemp.Width;
            viHeight = bmpTemp.Height;
            while (viWidth % 2 != 0)
            {
                viWidth--;
            }
            while (viHeight % 2 != 0)
            {
                viHeight--;
            }
            bmpStart = new Bitmap(viWidth, viHeight);
            graphWork = Graphics.FromImage(bmpStart);
            graphWork.DrawImage(bmpTemp, new Rectangle(0, 0, viWidth, viHeight), 0, 0, bmpTemp.Width, bmpTemp.Height, GraphicsUnit.Pixel);
            graphWork.Dispose();
            //Освобождаем картинку, чтобы не держала файл рисунка   
            bmpTemp.Dispose();
            //Забираем все пиксели с картинки в массив указателей
            bmpBytesSource = new Byte[viWidth * viHeight * 4];
            BitmapData bmpTempDataStart = bmpStart.LockBits(new Rectangle(0, 0, viWidth, viHeight), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
            unsafe
            {

                try
                {

                    Marshal.Copy(bmpTempDataStart.Scan0, bmpBytesSource, 0, viWidth * viHeight * 4);

                }
                catch (Exception)
                {
                }
                finally
                {
                    bmpStart.UnlockBits(bmpTempDataStart);
                    bmpTempDataStart = null;

                }
            }

            brgPixelsB = new byte[viWidth, viHeight];
            brgPixelsG = new byte[viWidth, viHeight];
            brgPixelsR = new byte[viWidth, viHeight];
            brgPixelsL = new byte[viWidth, viHeight];

            //Забираем в массивы все биты источника, рассортировав их по ARGB 
            for (int i = 0; i < viWidth; i++)
            {
                for (int j = 0; j < viHeight; j++)
                {
                    brgPixelsB[i, j] = bmpBytesSource[i * 4 + (j * viWidth * 4)];
                    brgPixelsG[i, j] = bmpBytesSource[i * 4 + (j * viWidth * 4) + 1];
                    brgPixelsR[i, j] = bmpBytesSource[i * 4 + (j * viWidth * 4) + 2];
                    brgPixelsL[i, j] = bmpBytesSource[i * 4 + (j * viWidth * 4) + 3];


                }
            }
            double dRadCone = (double)bmpStart.Width / ((double)2 * Math.PI);
            radius = (int)dRadCone;
            while (radius % 2 != 0)
            {
                radius--;
            }

            bitmapWork = new Bitmap(2 * radius, bmpStart.Height);
            graphWork = Graphics.FromImage(bitmapWork);
            graphWork.Clear(Color.FromArgb(0, 0, 0));           
            graphWork.DrawArc(new Pen(Color.FromArgb(255, 0, 0), 1), 0, bmpStart.Height - radius,
                2 * radius - 1, radius - 1,0,180);
            //bitmapWork.Save("1.bmp");
           

            Color cl;
            
            
            //Точки снизу
            virgPointsL=new int[radius];

            
            viLength = new int[radius];
            int[] viLength1 = new int[radius];            
            for (int m = radius - 1; m >= 0; m--)
            {               
                for (int n = bitmapWork.Height - 1; n >= 0; n--)
                {
                    cl = bitmapWork.GetPixel(m, n);
                    if (cl.R == 255)
                    {
                        virgPointsL[radius - 1 - m] = n;
                        viLength[radius - 1 - m] = (int)Math.Sqrt((radius - 1 - m) * (radius - 1 - m) + n * n);
                        break;
                    }
                }              
            }
            graphWork.Clear(Color.FromArgb(0, 0, 0));
            virgPoints = new int[radius, bitmapWork.Height];
            for (int m = 0; m < radius; m++)
            {   
                graphWork.Clear(Color.FromArgb(0, 0, 0)); 
                graphWork.DrawLine(new Pen(Color.FromArgb(255, 0, 0), 1), radius - 1, 0, radius - 1 - m, virgPointsL[m]);                 

                for (int j = 0; j < bitmapWork.Height; j++)
                {
                 
                    for (int i = 0; i < bitmapWork.Width/2+1; i++)
                    {
                        cl = bitmapWork.GetPixel(i, j);
                        if (cl.R == 255)
                        {   
                            virgPoints[m, j] = i;                            
                            break;
                        }
                    }
                }                

            }
           
            
            myForm.WindowState = System.Windows.Forms.FormWindowState.Normal;
            myForm.Width = bmpStart.Width;
            myForm.Height = bmpStart.Height + 200;
            myForm.Left = (myForm.screen.Width - myForm.Width) / 2;
            myForm.Top = (myForm.screen.Height - myForm.Height) / 2;
            myForm.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
            viI = 0;
            viJ = 0;
            fBlock = false;
        }

        internal void LineTick()
        {
           
            if (fBlock) return;

            viJ += 1;
            if (viJ % 5 != 0) return;

            fBlock = true;

            double CosL;
            double SinL;
            double TgL;
            graphWork.Clear(Color.FromArgb(0, 0, 0, 0));
            bmpBytesFore = new byte[2 * radius * bitmapWork.Height * 4];
            //Двигаемся по увеличению радиуса хранящегося по линиям (, начала дуг слева направо  в virgPoints
            for (int R = 0; R < radius; R++)
            {
                //длина линии для радиуса 
                viLengthP = viLength[R];

                //Соотношение с исходным радиусом четвертушки дуги - НА СКОЛЬКО Меньше 
                //koefX = (double)viLengthP / (double)bitmapWork.Height;
                //
                //koefY = (double)radius / viHeight / (double)2;
                koefX = (double)radius / ((double)viWidth / (double)2);
                //koefX = (double)radius / ((double)viWidth);
                koefY = 1;
                //Пойдём вниз, от 0  
                for (int j = 0; j < bitmapWork.Height; j++)
                {
                    //Точуа встречи слева направо для данного R
                    pointMittingX = virgPoints[R, j];
                    if (pointMittingX == 0) continue;
                    
                    //Ищем сохранённую точку счтречи слева направа 
                    for (int i = 0; i <= radius; i++)
                    {
                        //Достигли точки встречи 
                        if (i >= pointMittingX)
                        {




                            CosL = viLengthP == 0 ? 1 : (double)j / (double)viLengthP;
                            SinL = 1 - CosL;
                            TgL = CosL == 0 ? 0 : SinL / CosL;

                            //Куда в массиве - это точка i j
                            viTo1 = j * (2 * radius) * 4 + i * 4;
                            // viFromY = (int)((double)j * (double)koefY);
                            // viFromX = i - (int)((double)i * CosL);
                            //viFromY = viHeight - 1 - (int)((double)j * (double)TgL);
                            //Случайное совпадение //Идеально
                            //koefX = (double)radius / (double)viHeight;
                            //viFromX = i + (int)(j * koefX);

                            

                            koefX = (double)radius / (double)viHeight;

                            koefX1 = (double)(radius - i) / (double)radius;

                            //viFromX =  i + (int)(((double)(radius - i) / (double)radius) * (j * koefX));
                            viFromX = i + (int)(koefX1 * (j * koefX));
                            //viFromX = i + (int)(j * koefX);
                            
                            

                            
                            
                           
                            //myForm.Text = viFromX.ToString();
                            viFromY = j;

                            
                             //viFromX = i;


                            try
                            {
                                viFromX = (viFromX + viI) % viWidth;
                                bmpBytesFore[viTo1] = brgPixelsB[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 1] = brgPixelsG[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 2] = brgPixelsR[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 3] = brgPixelsL[viFromX, viFromY];


                                viTo1 = (j + 1) * (2 * radius) * 4 - i * 4 -4;

                                //viFromX = radius-i- (int)(koefX1 * (j * koefX));                                
                                viFromX = 2*radius - i - (int)(koefX1 * (j * koefX));                                 
                                

                                viFromX = (viFromX + viI) % viWidth;
                                bmpBytesFore[viTo1] = brgPixelsB[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 1] = brgPixelsG[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 2] = brgPixelsR[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 3] = brgPixelsL[viFromX, viFromY];




                            }
                            catch (Exception ex)
                            {
                                myForm.Text = ex.Message;
                            }
                            break;
                        }


                    }





                }


            }
            //for (int i = 0; i < 2 * radius; i++)
            //{
            //    for (int j = 0; j < 2 * radius; j++)
            //    {
            //        bmpBytesFore[j * (2 * radius) * 4 + i * 4] = brgPixelsB[i, j];
            //        bmpBytesFore[j * (2 * radius) * 4 + i * 4 + 1] = brgPixelsG[i, j];
            //        bmpBytesFore[j * (2 * radius) * 4 + i * 4 + 2] = brgPixelsR[i, j];
            //        bmpBytesFore[j * (2 * radius) * 4 + i * 4 + 3] = brgPixelsL[i, j];
            //    }
            //}




            BitmapData bitmapData = bitmapWork.LockBits(new Rectangle(0, 0, bitmapWork.Width, bitmapWork.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
            unsafe
            {
                Marshal.Copy(bmpBytesFore, 0, bitmapData.Scan0, bmpBytesFore.Length);

            }
            bitmapWork.UnlockBits(bitmapData);

            myForm.pictureBox1.Image = bitmapWork;

            viI++;

            fBlock = false;
        }
    }
}
