From lines to mesh. How to describe a lot of lines with a square grid?

Good afternoon. I am looking for a way to turn about 40,000 lines into a square grid repeating their pattern. The method should be easy so that the result of this grid (or rather, an array of the obtained points) can be compared with a similar pattern … These are just lines and they do not go out of the circle. Please help …

this might work for your purpose
but it will become slow if you have lots of curves

Squared_Grid.gh (10.4 KB)

Thanks for the answer, Inno) I wrote in the question that it is about 40,000 lines) this definitely can’t solve my problem…
Regards

Render it as an image, then apply a threshold filter?

Thanks for the answer,Daniel) This should work instantly when changing the model. The fact is that I plan to exclude lines and compare the result with the one I need. This is a huge number of iterations and my life is not enough to save and compare everything. I plan to use the Galapagoss further to rule out lines. If I manage to solve this…Help me, please
Regards)

Are you trying to do something like this?

Yes, and I did not find the answer to this problem with a grasshopper in the public domain for sure. I read and looked at a lot of articles, but I don’t know programming languages … I need to do this precisely through the grasshopper, because in the future I plan to do this using color. I figured out how to get around all the other problems, but problems with detail remain. As a result, I came to the conclusion that if you solve this small problem, everything will work out.

This all can not help me to the end because I don’t know how to program) Just help me solve this problem specifically)



http://erikdemaine.org/fonts/stringart/?text=Elbzaveta&font1500=1

I also got this) But the delalization that I got is not suitable for me because I need it for implementation in a physical place

I think you’ll really struggle to do this with only standard components and no looping.

If you have 40k lines each of which you either reject or keep, that’s 2^40k possible combinations. It’s not realistic to brute force that.

What would you suggest me to do?) I just don’t know for myself other ways) Maybe something will work) In general, I don’t care which method to use … I just want to solve this problem with the further possibility of editing and detailing it through Grasshopper
I apologize in advance for my English)
Regards

Hi @alenustins.

What Daniel told you basically means that you can’t achieve what you want with Grasshopper. You need to code the logic in a programming language like C# or Python. Grasshopper includes one component for each of these languages so that you can write/type. your program in there.

Also, let me suggest, if English isn’t your native language, check this.

Instead of saying “Then suggest a method”. You could say “What would you suggest me to do?”

Hope this helps to clarify somethings, good luck.

1 Like

Hello,
so you don’t program and you want to be able to add color quite a bit odd but whatever I tried to orient you in the direction on the grasshopper forum.
I don’t want to give my code but I let some clues for a good samaritin !

The algorithm is quite simple
Make an image in memory (a 2D array (grey) or 3 2D array (color)
Place N (~100 to 1000) points around
Choose a first point

For all itterations (1000 to 4000)
_For all pins
___Draw a line (white or black with transparency)
___Count how much color it removes from the image
___Track this percentage of removal
_End for all pins
_Choose the line that remove the maximum of color
Repeat until the end of all itterations

I recommand to use array of double to represent image, that is far faster than windows image
Use antialising to draw the line

I make a voice recognition program to help me placing the thread. I say “Next” to the computer and it gives me the next number. It writes also the numbers on the screen. See the code
I also make GCode to drill the holes (here 200 holes code for 600 mm square panel)
20181207_200trous_600mm600mm.txt (15.7 KB)

Quite lot of work …

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Speech.Recognition;
using System.Speech.Synthesis;
using System.IO;

namespace LectureFichierNombres
{
    public partial class Form1 : Form
    {
        SpeechSynthesizer synth;
        IReadOnlyCollection<InstalledVoice> voices;
        int voiceIndex;

        public int indexOfNumber;
        List<int> numbers;


        SpeechRecognitionEngine recEngine;

      

        public Form1()
        {
            //The voices
            voiceIndex = 0;
            InitializeComponent();
            synth = new SpeechSynthesizer();
            voices = synth.GetInstalledVoices();         
            foreach (InstalledVoice voice in voices)
            {
                this.listBoxVoices.Items.Add(voice.VoiceInfo.Name);
            }
            listBoxVoices.SelectedIndex = 0;

            //Voic recognition
            Choices commands = new Choices();
            commands.Add(new String[] { "suivant", "next", "plus"});
            GrammarBuilder gBuilder = new GrammarBuilder();
            gBuilder.Append(commands);
            Grammar gram = new Grammar(gBuilder);
            recEngine = new SpeechRecognitionEngine();
            recEngine.LoadGrammar(gram);
            recEngine.SetInputToDefaultAudioDevice();

            recEngine.SpeechRecognized += RecEngine_SpeechRecognized;
            recEngine.RecognizeAsync(RecognizeMode.Multiple);

            label1.Text = Properties.Settings.Default.setFilePath;
            numbers = new List<int>();
            PopulateNumbers();

   
            this.FormClosing += Form1_FormClosing;
            this.checkBox1.Checked = Properties.Settings.Default.setWithVoice;
            SetLabels();
        }


        private void PopulateNumbers()
        {
            if (File.Exists(Properties.Settings.Default.setFilePath))
            {
                string[] lines = System.IO.File.ReadAllLines(Properties.Settings.Default.setFilePath);
                numbers.Clear();
                indexOfNumber = Properties.Settings.Default.setLastIndex ;
                foreach (String line in lines)
                {
                    int number;
                    if (Int32.TryParse(line, out number))
                    {
                        numbers.Add(number);
                    }
                }
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Save all the information concerning the session
            Properties.Settings.Default.Save();
        }

        private void PrecIndex(bool withVoice)
        {
            indexOfNumber-= 1;
            if (indexOfNumber >= 0 && indexOfNumber < numbers.Count)
            {
                if (withVoice)
                    synth.Speak(" "+numbers[indexOfNumber]);
                SetLabels();
                SaveHistory("PREV", indexOfNumber, numbers[indexOfNumber]);
            }
        }
        private void NextIndex(bool withVoice)
        {
            indexOfNumber += 1;
            if (indexOfNumber >=0 && indexOfNumber < numbers.Count)
            {
                Properties.Settings.Default.setLastIndex = indexOfNumber;
                if (withVoice)
                    synth.Speak(" " + numbers[indexOfNumber]);

                SaveHistory("NEXT", indexOfNumber, numbers[indexOfNumber]);

            }
            SetLabels();

        }
        
        private void RecEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            if (e.Result.Confidence > 0.750)
            {
                labelRecogniton.Text = "Je comprends " + e.Result.Confidence.ToString();
                switch (e.Result.Text)
                {
                    case "suivant": NextIndex(Properties.Settings.Default.setWithVoice); break;
                    case "next": NextIndex(Properties.Settings.Default.setWithVoice); break;
                    case "plus": NextIndex(Properties.Settings.Default.setWithVoice); break;                   
    
                    default:
                        synth.Speak("Bla Bla");
                        break;
                };
            }
            else
            {
                labelRecogniton.Text = "Je ne comprends pas "+ e.Result.Confidence.ToString();
            }
          //  throw new NotImplementedException();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
         
        }

        private void listBoxVoices_ControlAdded(object sender, ControlEventArgs e)
        {
           
        }

        private void comboBox1_ControlAdded(object sender, ControlEventArgs e)
        {
         
        }

        private void listBoxVoices_SelectedIndexChanged(object sender, EventArgs e)
        {
            voiceIndex = listBoxVoices.SelectedIndex;
        }


        private void button1_Click(object sender, EventArgs e)
        {
            //synth.Speak("Voix de"+ voices.ElementAt(voiceIndex).VoiceInfo.Name);
            var fileContent = string.Empty;
            var filePath = string.Empty;
            var filePathHistory = string.Empty;

            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                if (filePath != null)
                openFileDialog.InitialDirectory = Properties.Settings.Default.setFilePath;
                openFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
                openFileDialog.FilterIndex = 0;
                openFileDialog.RestoreDirectory = true;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    //Get the path of specified file

                    if (File.Exists(openFileDialog.FileName))
                    {
                        filePath = openFileDialog.FileName;
                        filePathHistory = filePath + ".hist";
                        label1.Text = filePath;
                        
                        PopulateNumbers();
                        if  (Properties.Settings.Default.setFilePath != filePath)
                        {
                            Properties.Settings.Default.setFilePath = filePath;
                            this.indexOfNumber = 0;
                        }
                        if (Properties.Settings.Default.setFilePathHistory != filePathHistory)
                        {
                            Properties.Settings.Default.setFilePathHistory = filePathHistory;                            
                        }
                    }
                }
            }            
        }

        private void button2_Click(object sender, EventArgs e)
        {
            PrecIndex(false);
       
        }

        private void button3_Click(object sender, EventArgs e)
        {
            NextIndex(false);
    
        }
        private void SaveHistory(string text,int lineNumber, int pinNumber)
        {
            if (!File.Exists(Properties.Settings.Default.setFilePathHistory))
            {
                File.AppendAllText(Properties.Settings.Default.setFilePathHistory, "Direction, Line number, Pin number, Date" + Environment.NewLine);
 
            }
            File.AppendAllText(Properties.Settings.Default.setFilePathHistory, text + ", "+ lineNumber.ToString() + ", "+pinNumber.ToString()+", "+ DateTime.Now.ToString() + Environment.NewLine);             

        }
        private void SetLabels()
        {
            if ((indexOfNumber - 1) >= 0 && (indexOfNumber - 1) < numbers.Count)
            {
                labelIndexPrec.Text = (indexOfNumber - 1).ToString();
                labelNumberPrec.Text = numbers[indexOfNumber - 1].ToString();
            }
            else
            {
                labelIndexPrec.Text = "DEBUT";
                labelNumberPrec.Text = "DEBUT";
            }

            if ((indexOfNumber) >= 0 && (indexOfNumber ) < numbers.Count)
            {
                labelIndexActual.Text = (indexOfNumber).ToString();
                labelNumberActual.Text = numbers[indexOfNumber ].ToString();
            }
            else
            {
                labelIndexActual.Text = "?";
                labelNumberActual.Text = "?";
            }
            if ((indexOfNumber+1) >= 0 && (indexOfNumber+1) < numbers.Count)
            {
                labelIndexNext.Text = (indexOfNumber+1).ToString();
                labelNumberNext.Text = numbers[indexOfNumber+1].ToString();
            }
            else
            {
                labelIndexNext.Text = "FIN";
                labelNumberNext.Text = "FIN";
            }
        }
        private void Reset()
        {
            indexOfNumber = 0;
            SetLabels();
        }
        private void button4_Click(object sender, EventArgs e)
        {
            Reset();
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked) Properties.Settings.Default.setWithVoice = true;
            else Properties.Settings.Default.setWithVoice = false;
        }
    }
}
`
2 Likes

This is Python code

http://artof01.com/vrellis/works/knit.html

MeshTools Voxel component is quite fast and worth a look. (There are some other Voxel components around but they are usually much slower than this one).



Vox.gh (14.6 KB)

1 Like

I don’t understand why @alenustins wants mesh but the link and script Michael give is also like what was done on this discussion

2 Likes

I don’t understand why @alenustins wants mesh

I don’t think mesh is the goal. Here I use the voxel as a fast way to get that grid. That is why I intersect it at the end with a plane.

2 Likes

Thank you very much, Laurent!) I will try to use it somehow in my own decision … However, I probably will not be able to implement your solution) I am very grateful for your reply. Thanks you. I understand that you have work that you cannot share and I respect that. I will try to use all that is.
I apologize for my English) Google helps me)
Regards

Thank you, Michael! Your solution is very good! However, it counts 400 lines for about 5 seconds … It is assumed 100 times more. I almost found such a component in Decodingspaces, however, it depends on the fill point, therefore, when the number of lines decreases, it starts to skip sections as can be seen in the first picture in this thread. I guess there is a way to do this fast enough, what do you think?
Thanks again for the answer!) … and you are absolutely right, the final goal is the central points that are visible in these pictures))
Regards
https://toolbox.decodingspaces.net/#lab
%D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA
%D0%A1%D0%BD%D0%B8%D0%BC%D0%BE%D0%BA0

Yikes: How had the mighty fallen > you talk to a computer? > porca miseria > recycle that C# ASAP > never do that again > reset now for ever.

1 Like

If your curves are lines in one plane (XY plane) and you want to draw squares of given size along the lines it is quite simple and fast if you to do it by code.
Here is GH definition with C# component attached.
It finds bounding box of all lines (and slightly enlarge it).
Than by supplying input value of SquareSize you actually define dimension of grid in X and Y direction (Xcount an Ycount) which gives you total num of cells in 2D grid (Xcount * Ycount). This can be very huge number if “area” that Lines occupy is large and at the same time SquareSize is small.
Then algorithm for each line check which cell “intersects” with it and marked that cell (cellStaus[row,column]=true). So at the end we get status of all cells and can work further with it.
Problem comes if there is lot of cells and we want to display them somehow - it can happen that there are zillions of them and you do not want to try to display them as mesh - it will take long long time.
I attached photo of testing as well where testing was done with 37000+ of curves that occupy such area that if we use SquareSize of 1 it produce grid of 118 million of cells. Actual code will find all “intersecting cells” quite fast, in less then 300 milliseconds, total of 16+ million of cells found.
LinesToMesh_v31.gh (12.8 KB)

1 Like