c# - Cluster overlapping circles? -


i trying cluster(group) every circle that's uninterrupted overlapping (connected) each other how that? (preferably in pretty efficient way).

(i have messed around trying write recursive functions haven't gotten work.)

i have created vs project visualize problem.

download here:

generates random circles. enter image description here

how clustering works: (its looks @ circle overlapping specific circle not connected) enter image description here

how should if working (separate clusters connecting circles) enter image description here

code: (c#)

using system; using system.collections.generic; using system.componentmodel; using system.data; using system.drawing; using system.linq; using system.text; using system.windows.forms;  // cluster overlapping circles // patrik fröhler // www.patan77.com // 2017-08-14  namespace circlegroup {     struct circle // circle "object"     {         public float[] pos;         public int radius;         public color color;         public int id;         public float x         {             { return pos[0]; }             set { pos[0] = value; }         }         public float y         {             { return pos[1]; }             set { pos[1] = value; }         }     }      public partial class form1 : form     {         db _db = new db(); // "global database"          public form1()         {             initializecomponent();         }          private static circle createcircle(float _x = 0, float _y = 0, int _radius = 1, color? _color = null, int _id = -1) // creates circle         {             circle tmpcircle = new circle() { pos = new float[2], x = _x, y = _y, radius = _radius, id = _id };             tmpcircle.color = _color ?? color.black;             return (tmpcircle);         }          private circle[] genrngcircles(int _n) // generates array of random circles         {             random rng = new random();             circle tmpc;             circle[] tmpcarr = new circle[_n];             (int = 0; < _n; i++)             {                 tmpc = createcircle();                 tmpc.radius = rng.next(10, 75);                 tmpc.x = rng.next(tmpc.radius, (512 - tmpc.radius));                 tmpc.y = rng.next(tmpc.radius, (512 - tmpc.radius));                 tmpc.color = color.fromargb(127, rng.next(0, 255), rng.next(0, 255), rng.next(0, 255));                 tmpc.id = i;                 tmpcarr[i] = tmpc;              }             return tmpcarr;         }          private void drawcircle(circle _circle, graphics _g) // draws 1 circle         {             solidbrush sb = new solidbrush(_circle.color);             _g.fillellipse(sb, (_circle.x - _circle.radius), (_circle.y - _circle.radius), (_circle.radius * 2), (_circle.radius * 2));             sb.dispose();         }          private void drawstring(float[] _pos, string _text, graphics _g) // draws text         {             stringformat sf = new stringformat();             sf.linealignment = stringalignment.center;             sf.alignment = stringalignment.center;             font font = new font("arial", 12);             solidbrush sb = new solidbrush(color.black);             float x = _pos[0];             float y = _pos[1];             _g.drawstring(_text, font, sb, x, y, sf);             font.dispose();             sb.dispose();         }          private void drawcirclearr(circle[] _circlearr, graphics _g)// draws array of circles         {             _g.clear(panel1.backcolor);             (int = 0; < _circlearr.length; i++)             {                 drawcircle(_circlearr[i], _g);                 drawstring(_circlearr[i].pos, _circlearr[i].id.tostring(), _g);             }         }          static double mdistance<t>(t[] _p0, t[] _p1) // gets euclidean distance between 2 points of arbitrary numbers of dimensions         {             double[] p0 = new double[] { convert.todouble(_p0[0]), convert.todouble(_p0[1]) };             double[] p1 = new double[] { convert.todouble(_p1[0]), convert.todouble(_p1[1]) };             double tmp = 0;             double tmptotal = 0;             (int = 0; < _p0.length; i++)             {                 tmp = (p0[i] - p1[i]);                 tmptotal += (tmp * tmp);             }             double output = math.sqrt(tmptotal);             return (output);         }          private bool overlap(circle _c0, circle _c1) // checks if 2 circles overlap         {             double dis = mdistance(_c0.pos, _c1.pos);             if (dis <= (_c0.radius + _c1.radius))             {                 return (true);             }             return (false);         }          private color avgcolor(list<circle> _colorarr) // averages mutiple colors togehter         {             float ia = 0;             float ir = 0;             float ig = 0;             float ib = 0;             (int = 0; < _colorarr.count; i++)             {                 ia += _colorarr[i].color.a;                 ir += _colorarr[i].color.r;                 ig += _colorarr[i].color.g;                 ib += _colorarr[i].color.b;             }             byte = convert.tobyte(math.round(ia / _colorarr.count));             byte r = convert.tobyte(math.round(ir / _colorarr.count));             byte g = convert.tobyte(math.round(ig / _colorarr.count));             byte b = convert.tobyte(math.round(ib / _colorarr.count));              return (color.fromargb(a, r, g, b));         }          private void treeview(list<circle>[] _circlelarr) // create treeview         {             treeview1.nodes.clear();             (int = 0; < _circlelarr.length; i++)             {                 treeview1.nodes.add(i.tostring());                 (int j = 0; j < _circlelarr[i].count; j++)                 {                     treeview1.nodes[i].nodes.add(_circlelarr[i][j].id.tostring());                 }             }             treeview1.expandall();         }          private void drawcircleclusters(list<circle>[] _circlelarr, graphics _g) // draws circle clusters         {             _g.clear(panel1.backcolor);             circle tmpc;             color tmpcolor;             (int = 0; < _circlelarr.length; i++)             {                 tmpcolor = avgcolor(_circlelarr[i]);                 (int j = 0; j < _circlelarr[i].count; j++)                 {                     tmpc = _circlelarr[i][j];                     tmpc.color = tmpcolor;                     drawcircle(tmpc, _g);                     drawstring(_circlelarr[i][j].pos, _circlelarr[i][j].id.tostring(), _g);                 }             }         }          //----------------------------------------------------          private list<circle>[] simpleoverlap(circle[] _circlearr) // test circles overlaps          {             list<circle>[] tmplarr = new list<circle>[_circlearr.length];             (int = 0; < (_circlearr.length); i++)             {                 tmplarr[i] = new list<circle>();                 (int j = 0; j < (_circlearr.length); j++)                 {                     if (overlap(_circlearr[i], _circlearr[j]))                     {                         tmplarr[i].add(_circlearr[j]);                     }                 }              }             return (tmplarr);         }          /*         private circle[] recuroverlap(circle[] _circlearr) // recursive overlap test(not done/working)         {             list<circle> overlaparr = new list<circle>();             list<circle> dontoverlaparr = new list<circle>();             bool loop = true;             int n = 0;             while (loop)             {                 if (overlap(_circlearr[0], _circlearr[n]))                 {                     overlaparr.add(_circlearr[n]);                     dontoverlaparr.insert(0, _circlearr[n]);                     circle[] dontarr = dontoverlaparr.toarray();                     recuroverlap(dontarr);                 }                 else                 {                     dontoverlaparr.add(_circlearr[n]);                 }                 n++;                 if (n >= _circlearr.length)                 {                     loop = false;                 }             }             if(_circlearr.length <= 1)             {                 return _circlearr;             }             else{                 return overlaparr.toarray();             }          }          private list<circle>[] clusterbrecur(circle[] _circlearr)         {             list<circle>[] tmplarr = new list<circle>[_circlearr.length];             (int = 0; < (_circlearr.length); i++)             {                 tmplarr[i] = new list<circle>();                 recuroverlap(_circlearr);             }             return (tmplarr);         }*/           private void run() // run function         {             treeview1.nodes.clear(); // clear tree view             _db.g = panel1.creategraphics();// create panel graphics draw on             _db.circlearr = genrngcircles(10); // creates array random circles             drawcirclearr(_db.circlearr, _db.g); // draws random circles             clusterabtn.enabled = true; // enables cluster button         }          private void clustera() // clustera function         {             _db.circleclusters = simpleoverlap(_db.circlearr); // runs cluster algorithm test             treeview(_db.circleclusters); // creates treeview             drawcircleclusters(_db.circleclusters, _db.g); // draws circle clusters         }          private void clusterb()         {          }          private void clustera_rclick()         {             drawcirclearr(_db.circlearr, _db.g); // draws random circles         }          private void runbtn_click(object sender, eventargs e) // run button click         {             run();         }          private void clusterabtn_mouseup(object sender, mouseeventargs e)          {             switch (e.button)             {                 case mousebuttons.left:                     clustera();                     break;                 case mousebuttons.right:                     clustera_rclick();                     break;             }         }          private void clusterbbtn_click(object sender, eventargs e) // clusterb button click         {             clusterb();         }     }      class db // "database"     {         public graphics g;         public circle[] circlearr;         public list<circle>[] circleclusters;     } } 

the current "overlap function"

    private list<circle>[] simpleoverlap(circle[] _circlearr) // test circles overlaps      {         list<circle>[] tmplarr = new list<circle>[_circlearr.length];         (int = 0; < (_circlearr.length); i++)         {             tmplarr[i] = new list<circle>();             (int j = 0; j < (_circlearr.length); j++)             {                 if (overlap(_circlearr[i], _circlearr[j]))                 {                     tmplarr[i].add(_circlearr[j]);                 }             }          }         return (tmplarr);     } 

i made following change code. looks working

    private list<circle>[] simpleoverlap(circle[] _circlearr) // test circles overlaps      {         list<list<circle>> list = new list<list<circle>>();          //list<circle>[] tmplarr = new list<circle>[_circlearr.length];         //for (int = 0; < (_circlearr.length); i++)         foreach (circle circle in _circlearr)         {             list<circle> cluster = null;             //tmplarr[i] = new list<circle>();             //for (int j = 0; j < (_circlearr.length); j++)             //{             //    if (overlap(_circlearr[i], _circlearr[j]))             //    {             //        tmplarr[i].add(_circlearr[j]);             //    }             //}             foreach(list<circle> cluster2 in list)             {                 foreach (circle circle2 in cluster2)                 {                     if (overlap(circle, circle2))                     {                         cluster = cluster2;                         goto label_001;                     }                 }             }             label_001:             if (cluster == null)             {                 cluster = new list<circle>();                 list.add(cluster);             }             cluster.add(circle);         }          bool flag = true;         (int = 0; < list.count; += (flag ? 1 : 0))         {             flag = true;             list<circle> cluster = list[i];             (int j = + 1; j < list.count; j++)             {                 list<circle> cluster2 = list[j];                 if (intersects(cluster, cluster2))                 {                     cluster.addrange(cluster2);                     list.remove(cluster2);                     j--;                     flag = false;                 }             }         }          return list.toarray();         //return (tmplarr);     }      bool intersects(list<circle> cluster1, list<circle> cluster2)     {         foreach (circle circle1 in cluster1)         {             foreach (circle circle2 in cluster2)             {                 if (overlap(circle1, circle2))                 {                     return true;                 }             }         }         return false;     } 

i had add 1 more method bool intersects(list<circle> cluster1, list<circle> cluster2). see if helps.


Comments

Popular posts from this blog

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -