SORU
16 Temmuz 2010, Cuma


Dışarı örtüşen dikdörtgenler alanı için bir algoritma?

Bu sorun aslında roll-over ile ilgilenir, sadece aşağıdaki gibi genelleştirilmiş edeceğim:

2 BOYUTLU bir görünümü var, ve ekranda bir alan içinde dikdörtgenler bir dizi var. Bu kutuları üst üste, ama sadece minimal hareket ile onları ayarlamak yok böyle yayıldı?

Dikdörtgenler konumlarını ve kullanıcı giriş dinamik bağımlı, pozisyonlarını her yerde olabilir.

alt text ekli resimler göstermek ve çözüm istiyorlardı

Gerçek hayattaki sorun, takla, aslında ilgilenir.

Yorum soruların cevaplarını

  1. Dikdörtgenlerin boyutu sabit değildir, ve birsürü metnin uzunluğuna bağlıdır

  2. Ekran boyutu hakkında şu anda daha iyi ekran boyutu dikdörtgenler için yeterli olduğunu varsaymak yanlış olmaz sanırım. Çok dikdörtgenler var ve algo çözüm üretir, o zaman ben sadece içeriği değiştirmek zorunda.

  3. 'Minimal' mutlak bir mühendislik gereksinimi daha asethetics için daha fazla. hareket etmek için gereksinim Tek arasında çok büyük bir mesafe ekleyerek iki dikdörtgenin alanı olabilir, ama GUİ parçası olarak iyi görünmez. Fikir olarak yakın kaynak/dikdörtgen aktarma sonra siyah bir çizgi ile kaynağına bağlanmak benim olacak). Ya da 'hareket için sadece bir x' veya 'x' gayet iyi. yarım taşınıyordu

CEVAP
19 Temmuz 2010, PAZARTESİ


Biraz bu çalışıyordum ben de benzer bir şey gerektiği gibi, ama algoritma geliştirme ertelemiştim. Bana biraz itici :D almak için yardım ettin

Ben de kaynak kodu, bu yüzden burada gerekli. İncelenmiştir işe yaradı, ama oldukça işlevsel özelliklerini kullanmadım, herhangi bir prosedür dile çevirmek kolay olacak sanırım.

Tarihi bir bakış açısı

İlk kesişim hesaplamak için daha kolay çünkü çevreleri için algoritma geliştirmeye karar verdim. Sadece merkezleri ve yarıçapları bağlıdır.

* Denklem çözücü kullanma şansım oldu ve güzel bir performans.

Sadece bak:

alt text

Kolay oldu. Ben sadece aşağıdaki sorun çözücü yüklü:

For each circle
 Solve[
  Find new coördinates for the circle
  Minimizing the distance to the geometric center of the image
  Taking in account that
      Distance between centers > R1 R2 *for all other circles
      Move the circle in a line between its center and the 
                                         geometric center of the drawing
   ]

Bu kadar basit, ve Sturm yaptığın bütün işi.

"Ha!" dedim kolay, şimdi dikdörtgenler için gidelim!". Ama yanılmışım ...

Dikdörtgen Blues

Dikdörtgenler ile ana sorun, kavşak sorgulamak kötü bir fonksiyonudur. Gibi bir şey

Denklemi için bu durumlardan bir sürü Sturm yem denedim, bir şey yapmaya karar verdim o kadar çok prosedür uygulandı.

Benim algoritma aşağıdaki gibi sona erdi

Expand each rectangle size by a few points to get gaps in final configuration
While There are intersections
    sort list of rectangles by number of intersections
    push most intersected rectangle on stack, and remove it from list
// Now all remaining rectangles doesn't intersect each other
While stack not empty
    pop  rectangle from stack and re-insert it into list
    find the geometric center G of the chart (each time!)
    find the movement vector M (from G to rectangle center)
    move the rectangle incrementally in the direction of M (both sides) 
                                                 until no intersections  
Shrink the rectangles to its original size

"En küçük" durumu tamamen memnun (tek yönde). hareket unutmayın Ama herhangi bir yöne dikdörtgenler, bazen tatmin etmek için hareket eden kafa karıştırıcı bir harita ile kullanıcı için değişen biter buldum.

Kullanıcı arayüzü tasarımı olduğum gibi, dikdörtgen, biraz daha fazla, ama daha öngörülebilir bir şekilde hareket etmeyi seviyorum. Çok daha zorlu olacak, ancak her açıdan incelemek ve tüm yarıçapları boş bir yer bulunana kadar geçerli konumu etrafındaki algoritmasını değiştirebilirsiniz.

Her neyse, bu sonuçları örnektir (öncesi ve sonrası):

alt text

"Minimum hareket ama sonuçlar yeterince iyi" memnun değil. bu görebilirsiniz,

SVN benim depo ile biraz sorun yaşıyorum çünkü kodu postalayacağım. Bu sorunlar çözülünce çıkarırım.

Düzenleme:

Ayrıca dikdörtgen kavşakları bulmak için R-Trees kullanabilirsiniz, ama dikdörtgenler az sayıda ile başa çıkmak için bir overkill gibi görünüyor. Ve algoritmaları zaten alet olmadım. Belki de başka birini seçtiğiniz platform varolan bir uygulama için bir işaret olabilir.

Uyarı! Kod değil çok kaliteli .. ilk bir yaklaşım henüz, ve mutlaka bazı hatalar var.

Sturm.

(*Define some functions first*)

Clear["Global`*"];
rn[x_] := RandomReal[{0, x}];
rnR[x_] := RandomReal[{1, x}];
rndCol[] := RGBColor[rn[1], rn[1], rn[1]];

minX[l_, i_] := l[[i]][[1]][[1]]; (*just for easy reading*)
maxX[l_, i_] := l[[i]][[1]][[2]];
minY[l_, i_] := l[[i]][[2]][[1]];
maxY[l_, i_] := l[[i]][[2]][[2]];
color[l_, i_]:= l[[i]][[3]];

intersectsQ[l_, i_, j_] := (* l list, (i,j) indexes, 
                              list={{x1,x2},{y1,y2}} *) 
                           (*A rect does intesect with itself*)
          If[Max[minX[l, i], minX[l, j]] < Min[maxX[l, i], maxX[l, j]] &&
             Max[minY[l, i], minY[l, j]] < Min[maxY[l, i], maxY[l, j]], 
                                                           True,False];

(* Number of Intersects for a Rectangle *)
(* With i as index*)
countIntersects[l_, i_] := 
          Count[Table[intersectsQ[l, i, j], {j, 1, Length[l]}], True]-1;

(*And With r as rectangle *)
countIntersectsR[l_, r_] := (
    Return[Count[Table[intersectsQ[Append[l, r], Length[l]   1, j], 
                       {j, 1, Length[l]   1}], True] - 2];)

(* Get the maximum intersections for all rectangles*)
findMaxIntesections[l_] := Max[Table[countIntersects[l, i], 
                                       {i, 1, Length[l]}]];

(* Get the rectangle center *)
rectCenter[l_, i_] := {1/2 (maxX[l, i]   minX[l, i] ), 
                       1/2 (maxY[l, i]   minY[l, i] )};

(* Get the Geom center of the whole figure (list), to move aesthetically*)
geometryCenter[l_] :=  (* returs {x,y} *)
                      Mean[Table[rectCenter[l, i], {i, Length[l]}]]; 

(* Increment or decr. size of all rects by a bit (put/remove borders)*)
changeSize[l_, incr_] :=
                 Table[{{minX[l, i] - incr, maxX[l, i]   incr},
                        {minY[l, i] - incr, maxY[l, i]   incr},
                        color[l, i]},
                        {i, Length[l]}];

sortListByIntersections[l_] := (* Order list by most intersecting Rects*)
        Module[{a, b}, 
               a = MapIndexed[{countIntersectsR[l, #1], #2} &, l];
               b = SortBy[a, -#[[1]] &];
               Return[Table[l[[b[[i]][[2]][[1]]]], {i, Length[b]}]];
        ];

(* Utility Functions*)
deb[x_] := (Print["--------"]; Print[x]; Print["---------"];)(* for debug *)
tableForPlot[l_] := (*for plotting*)
                Table[{color[l, i], Rectangle[{minX[l, i], minY[l, i]},
                {maxX[l, i], maxY[l, i]}]}, {i, Length[l]}];

genList[nonOverlap_, Overlap_] :=    (* Generate initial lists of rects*)
      Module[{alist, blist, a, b}, 
          (alist = (* Generate non overlapping - Tabuloid *)
                Table[{{Mod[i, 3], Mod[i, 3]   .8}, 
                       {Mod[i, 4], Mod[i, 4]   .8},  
                       rndCol[]}, {i, nonOverlap}];
           blist = (* Random overlapping *)
                Table[{{a = rnR[3], a   rnR[2]}, {b = rnR[3], b   rnR[2]}, 
                      rndCol[]}, {Overlap}];
           Return[Join[alist, blist] (* Join both *)];)
      ];

Ana

clist = genList[6, 4]; (* Generate a mix fixed & random set *)

incr = 0.05; (* may be some heuristics needed to determine best increment*)

clist = changeSize[clist,incr]; (* expand rects so that borders does not 
                                                         touch each other*)

(* Now remove all intercepting rectangles until no more intersections *)

workList = {}; (* the stack*)

While[findMaxIntesections[clist] > 0,          
                                      (*Iterate until no intersections *)
    clist    = sortListByIntersections[clist]; 
                                      (*Put the most intersected first*)
    PrependTo[workList, First[clist]];         
                                      (* Push workList with intersected *)
    clist    = Delete[clist, 1];      (* and Drop it from clist *)
];

(* There are no intersections now, lets pop the stack*)

While [workList != {},

    PrependTo[clist, First[workList]];       
                                 (*Push first element in front of clist*)
    workList = Delete[workList, 1];          
                                 (* and Drop it from worklist *)

    toMoveIndex = 1;                        
                                 (*Will move the most intersected Rect*)
    g = geometryCenter[clist];               
                                 (*so the geom. perception is preserved*)
    vectorToMove = rectCenter[clist, toMoveIndex] - g;
    If [Norm[vectorToMove] < 0.01, vectorToMove = {1,1}]; (*just in case*)  
    vectorToMove = vectorToMove/Norm[vectorToMove];      
                                            (*to manage step size wisely*)

    (*Now iterate finding minimum move first one way, then the other*)

    i = 1; (*movement quantity*)

    While[countIntersects[clist, toMoveIndex] != 0, 
                                           (*If the Rect still intersects*)
                                           (*move it alternating ways (-1)^n *)

      clist[[toMoveIndex]][[1]]  = (-1)^i i incr vectorToMove[[1]];(*X coords*)
      clist[[toMoveIndex]][[2]]  = (-1)^i i incr vectorToMove[[2]];(*Y coords*)

            i  ;
    ];
];
clist = changeSize[clist, -incr](* restore original sizes*);

HTH!

Edit: Çok Açılı arıyor

Algoritma değişikliği her yöne arama yapmak için izin, ama ekseni geometrik simetri dayattığı tercih etmekten uygulanmaktadır.
Daha fazla devir pahasına, bu aşağıda gördüğünüz gibi daha kompakt nihai yapılandırmaları sonuçlandı:

enter image description here

Daha çok örnek 15**.

Ana döngü için yarı kod değişti:

Expand each rectangle size by a few points to get gaps in final configuration
While There are intersections
    sort list of rectangles by number of intersections
    push most intersected rectangle on stack, and remove it from list
// Now all remaining rectangles doesn't intersect each other
While stack not empty
    find the geometric center G of the chart (each time!)
    find the PREFERRED movement vector M (from G to rectangle center)
    pop  rectangle from stack 
    With the rectangle
         While there are intersections (list rectangle)
              For increasing movement modulus
                 For increasing angle (0, Pi/4)
                    rotate vector M expanding the angle alongside M
                    (* angle, -angle, Pi   angle, Pi-angle*)
                    re-position the rectangle accorging to M
    Re-insert modified vector into list
Shrink the rectangles to its original size

Eğer kullanabilirsiniz düşünüyorsanız kaynağı için kısaltma kodu, ama sadece istemek de dahil değilim. Bu şekilde giderseniz, daha iyi R-ağaçları (Aralık testler burada çok gerekli) geçmek için olduğunu düşünüyorum

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Digital Bounds

    Digital Boun

    19 Temmuz 2013
  • ibebrent

    ibebrent

    23 Temmuz 2007
  • MarinaHD2001

    MarinaHD2001

    7 ŞUBAT 2009