2011-12-09 15 views
13

पर स्थान तैयार करने की आवश्यकता है, यह समानांतर के सेट के लिए एक छवि, या कोई अन्य प्रतिनिधित्व उत्पन्न करने के बारे में एक प्रश्न है डेटा। ड्राइंग या जीयूआई प्रोग्रामिंग के बारे में नहीं है लेकिन गणना की स्थिति है। सबसे पहले मैं थोड़ा सा समझाऊंगा जहां मैं अभी खड़ा हूं और दूसरी छवि और उदाहरण मेरी समस्या दिखाता है।उन वस्तुओं से एक रैखिक, समयरेखा-आधारित, प्रतिनिधित्व उत्पन्न करना जो समय और वस्तुओं का उपभोग नहीं करते हैं, लेकिन अभी भी

वर्तमान स्थिति

exampleOne-Easy http://www.wargsang.de/text3935.png

मैं एक आयामी वस्तुओं है, लेकिन वे समानांतर पर उन्हें रखने "लाइनों" से गठबंधन कर रहे हैं। चलिए इस एक-आयामी वस्तुओं को "घटनाओं" कहते हैं जिनके पास समय की इकाई के रूप में "अवधि" होती है। इन घटनाओं में एक भिन्नता है जहां कुछ नहीं होता है, बिना किसी डेटा के ऑब्जेक्ट्स; एक "अंतराल" --object।

इसलिए हमें घटनाओं और अंतराल से युक्त सिमुलेटियस ऑब्जेक्ट्स के साथ एक समय सारिणी मिलती है, जो वस्तुओं की तीन सूचियों के रूप में संभालना बहुत आसान है। विज़ुअलाइज़ेशन भी सरल है: सूचियों पर लूप करें और प्रत्येक ऑब्जेक्ट को अपनी अवधि के अनुसार खींचें।

class Event(): 
    def __init__(self, duration, displacement = 0): #displacement is explained in the second example and the core problem of this question 
     self.duration = duration 
     self.displacement = displacement 
     #additional data 

    def self.draw(self, start_coordinate): 
     """draw duration * 10 pixels in black""" 
     #drawing code using start_coordinate to place the drawn object. see example graphic 
     return duration * 10 


class Gap(): 
    def __init__(self, duration, displacement = 0): 
     self.duration = duration 
     self.displacement = displacement 
     #no data 

    def self.draw(self, start_coordinate): 
     """draw duration * 10 pixels in transparent""" 
     #drawing code using start_coordinate to place the drawn object. see example graphic 
     return duration * 10 

row_one = [Event(1), Gap(1), Event(1), Gap(1), Event(1), Gap(1), Event(2)] 
row_two = [Event(1), Gap(2), Event(1), Event(1), Gap(1), Event(1), Gap(1), ] 
row_thr = [Gap(1), Event(1), Gap(1), Event(1), Gap(1), Event(3),] 

timetable = [row_one, row_two, row_thr] 

for row in timetable: 
    pixelcounter = 0 # the current position. 
    for item in row: 
     ret = item.draw(pixelcounter) #draw on the current position. Get how width the item was 
     pixelcounter += ret #save width for the next iteration   
    #instructions to move the "drawing cursor" down a few pixels so the next row does not overlap.  

समस्या

अब समस्या का। ऐसी वस्तुएं हैं जिन्हें ग्राफ़िकल स्पेस की आवश्यकता होती है लेकिन शून्य अवधि होती है। मैं इसे "विस्थापन" कहता हूं।

exampleTwo-Problematic http://www.wargsang.de/text4120.png

या हम जिन वस्तुओं पर अवधि है, लेकिन यह भी विस्थापन है की जरूरत है। यह अभी भी एक समस्या नहीं है जब हमारे पास केवल एक पंक्ति है, लेकिन पंक्तियों को सिंक्रनाइज़ करना अधिक जटिल है और मेरे पास इसका समाधान नहीं है।

लाल ब्लॉक के ऊपर की तस्वीर में शून्य अवधि होती है और विस्थापित होती है। ब्लू ब्लॉक की अवधि होती है और भी विस्थापित होती है।

उदाहरण: * विभिन्न वक्ता स्लॉट प्रत्येक घंटे (हमारे अवधि-स्लॉट) के साथ एक सम्मेलन के लिए एक समय सारिणी की कल्पना करें। प्रत्येक पंक्ति एक अलग सम्मेलन कक्ष का प्रतिनिधित्व करता है।

  • काले ब्लॉक भाषण हैं और शायद उनके भीतर एक संक्षिप्त विषय लिखा है (ग्राफिकल)।

  • ब्लू ब्लॉक भाषण भी हैं, लेकिन विषय लिखने में बहुत लंबा था इसलिए हमें एक बार और अधिक जगह चाहिए।

  • लाल कमरे के नंबर की तरह नोट्स हैं। वे अपने स्वयं के समय लेने के लिए नहीं है, लेकिन सभी आइटम जो उन्हें बाद आने के लिए संबंधित हैं। *

कार्य इतना है कि यह प्रत्येक पंक्ति के लिए सही है ऊपर समारोह से pixelcounter Calulate के लिए एक रास्ता मिल रहा है अकेले लेकिन यह भी कि एक पंक्ति में विस्थापन अन्य सभी पंक्तियों को प्रभावित करता है और वहां अतिरिक्त जगह बनाता है। लक्ष्य यह है कि प्रत्येक पंक्ति में अवधि तय और गठबंधन की जाती है। किसी भी घटना या अंतर को शुरू करना चाहिए, उदाहरण के लिए, इकाई-गणना 4, एक ही पूर्ण स्थिति पर शुरू होना चाहिए।

इसका मतलब है कि किसी भी शून्य-अवधि/विस्थापन वस्तु समय/अवधि में वास्तविक बिंदु पर शुरू होती है लेकिन किसी भी समय/अवधि का उपभोग नहीं करती है ताकि सभी आगामी आइटम उसी अवधि तक शुरू हो जाएं जब तक कि अगले वास्तविक अवधि की घटना न हो शामिल थे। किसी अन्य बिंदु से इसका अर्थ यह भी है कि शून्य अवधि की अवधि हमेशा की घटनाओं से पहले शुरू होती है।

तस्वीर में हम कॉलम 2 में एक साधारण मामला देख सकते हैं, जिसका अर्थ है कि यह दूसरी अवधि स्लॉट शुरू करता है। घटनाक्रम में उस कॉलम में तीन वास्तविक घटनाएं हैं जिन्हें दाईं ओर स्थानांतरित किया गया है क्योंकि एक विस्थापन वस्तु वहां है। कॉलम 4 में एक अवधि वस्तु है जिसमें विस्थापन भी है। दोबारा, स्लॉट 5 में शुरू होने वाली सभी वस्तुओं को दाईं ओर स्थानांतरित कर दिया गया है। कॉलम 6 सबसे दिलचस्प और मेरी असली समस्या है, मुझे यहां कोई समाधान नहीं मिल रहा है। फिर, कॉलम 6 में सभी वास्तविक घटनाओं को दाएं स्थानांतरित कर दिया गया है और फिर भी एक ही समय में शुरू होता है। लेकिन यहां हमारे पास एक है) विस्थापन-ऑब्जेक्ट्स दो पंक्तियों में और दो बी) एक दूसरे के पीछे दो वस्तुएं। इसलिए वास्तविक घटनाओं के लिए पूर्ण विस्थापन को जानना महत्वपूर्ण है, लेकिन तीसरी पंक्ति में दूसरी वस्तु के लिए भी महत्वपूर्ण है यह जानना कि इससे पहले एक और विस्थापन वस्तु है।

चेतावनी: ग्राफिकल प्रतिनिधित्व तालिका-आधारित दृष्टिकोण का सुझाव दे सकता है जहां प्रत्येक कॉलम की व्यक्तिगत चौड़ाई होती है। लेकिन यह वह जगह है जहां यह उदाहरण समाप्त होता है। असली एप्लिकेशन 300-10,000 प्रति घटना की सामान्य अवधि के साथ सौदा करता है लेकिन 1 की अवधि संभव नहीं है लेकिन तकनीकी रूप से संभव है। तो तालिका में एक अवधि की कॉलम-चौड़ाई होगी। ध्यान दें कि हमें सौ हजार पूर्ण अवधि (पंक्तियों की संख्या बार) मिल गई है, यह प्रदर्शन को खींच सकता है।

इस तस्वीर का डेटा इस तरह दिखेगा। मैं इस डेटा के साथ दूसरी छवि कैसे आकर्षित कर सकता हूं? या क्या बदलने की जरूरत है, मैं सभी सुझावों के लिए खुला हूं।

आपके समय और रुचि के लिए बहुत बहुत धन्यवाद। यदि आपको समाधान नहीं पता है तो कृपया मुझे प्रश्न पूछने में संकोच न करें या मुझे मेरी अवधारणा के दोष दिखाएं, इससे मुझे भी सोचने में मदद मिलेगी।

row_one = [ Event(1), #1 
      Event(0,1), Event(1), #2 
      Gap(1), #3 
      Event(1), #4 
      Gap(1), #5 
      Event(0,1), Event(1), #6 
      Event(1), #7 
      ] 
row_two = [ Event(1), #1 
      Event(1), #2 
      Gap(1), #3 
      Event(1, 0.5), #4, 0,5 is not important. we can also simply to just ints. The important bit is that it has both values. 
      Event(1), #5 
      Event(1), #6 
      Event(1), #7 
      ] 
row_thr = [ Event(1), #1 
      Event(1), #2 
      Event(1), #3    
      Event(1), #4 
      Event(1), #5    
      Event(0,1), Event(0,1), Event(1), #6 #Please pay attention to this case. 
      Event(1), #7 
      ] 
+0

ठीक है, सबसे पहले, क्या आप वाकई उनके लिए जगह रखना चाहते हैं? समय-बार के बजाय उन्हें प्रदर्शित करने के कुछ अन्य तरीकों के बजाय आप उन्हें अलग-अलग आकर्षित कर सकते हैं। –

+0

अफसोस की बात है, हाँ, मुझे उन सभी को एक पंक्ति पर चाहिए। – nilsge

+0

पंक्ति संख्या वाले सभी ऑब्जेक्ट्स को देखते हुए, एक ग्राफिकल चौड़ाई और समय चौड़ाई: आपको प्रत्येक ऑब्जेक्ट के लिए ग्राफ़िकल स्थिति ढूंढनी होगी, जैसे कि सभी पंक्तियां ग्राफ़िक रूप से फिट नहीं होतीं (कोई ओवरलैप नहीं) और सभी समान प्रारंभिक ग्राफिकल पर शुरू होते हैं पद। क्या वो सही है? – Ishtar

उत्तर

0

आपको एक्स समन्वय में अपना समय मैप करने के लिए एक फ़ंक्शन की आवश्यकता है। कठिन हिस्सा यह है कि आपको कभी-कभी एक पल में और अधिक जगह चाहिए। यह वस्तुओं की एक सूची के साथ हल किया जा सकता है, कह रहा है कि कब और कितनी अतिरिक्त जगह की आवश्यकता है।

function timeToLocation(t) 
    location = t * scale 
    for (o : extraSpaceList) 
    if o.when < t 
     location = location + o.space 
    return location 

जब भी तुम नोटिस वहाँ पर्याप्त जगह नहीं है (क्योंकि तत्वों ओवरलैप) एक वस्तु देने का प्रयास है, और, बस कुछ और अधिक स्थान वांछित पल में, सम्मिलित extraSpaceList.add({when=2s,space=4pixels})। सभी पंक्तियों को एक-एक करके प्रक्रिया करें, और फिर उन सभी को अंतिम स्थान के लिए फिर से संसाधित करें।

यदि आप अपनी ऑब्जेक्ट्स को प्रारंभ समय और ग्राफिकल आकार के लिए बदलते हैं तो यह आसान है। फिर गैप और इवेंट के बीच कोई अंतर नहीं है।

0

अगर मैं अपने प्रश्न समझ में ...

प्रत्येक कॉलम के लिए, पंक्तियों 'शून्य अवधि बक्से के अधिकतम चौड़ाई का ट्रैक रखने के रूप में आप प्रत्येक पंक्ति के एक प्रारंभिक प्रसंस्करण कर रहे हैं। जब आप अंततः प्रत्येक वास्तविक घटना को आकर्षित करते हैं, तो यह इसके कॉलम के लिए अधिकतम चौड़ाई मान के अंत में शुरू होता है। (मुझे लगता है कि आप पहले ही गणना कर रहे हैं कि कॉलम की शुरुआत कहां है।)

उपर्युक्त रंगीन ग्राफ में, पंक्ति 1 को प्रोसेस करने से आपको अधिकतम शून्य-अवधि की चौड़ाई (उदाहरण के लिए) [0, 10, 0, 0, 0, 10, 0]। पंक्ति 2 इसे बदल नहीं पाएगा। पंक्ति 3 इसे [0, 10, 0, 0, 0, 20, 0] में बदल देगा।

जब आप एक वास्तविक घटना खींचते हैं, तो यह इसके कॉलम_स्टार्ट + कॉलम अधिकतम-शून्य-अवधि-चौड़ाई से शुरू होगा।

0

मुझे आपके इवेंट कोड के साथ कुछ समस्याएं दिखाई देती हैं: 1) यह बताने का कोई तरीका नहीं है कि विस्थापन के लिए कितना स्थान आवंटित किया जाए, चाहे घटना शून्य अवधि हो या नहीं; 2) यदि आपके पास (पंक्ति चार में कहें) एक घटना जो 3 इकाइयां लेती है और 5 से शुरू होती है, तो इसे पूरी तरह से 5 और 6 स्लॉट में 7 से प्राप्त किए बिना पूरी तरह से खींचा जाएगा।

मुझे संदेह है कि आपको कुछ चाहिए जैसे:

class Event(object): 
    def __init__(self, duration, displacement=0): 
     self.duration = duration 
     self.displacement = displacement 
     self.width = max(STANDARD_WIDTH, duration+displacement) 
     #additional data 

    def self.draw(self, start_coordinate): 
     """draw duration * 10 pixels in black""" 
     return self.width * 10 

ग्राफ के रूप में ग्राफ के इलाज के बिना, मुझे यकीन नहीं है कि ऊपर उठाए गए दूसरे अंक के आसपास कैसे प्राप्त किया जाए।

इसके अलावा, इसमें दो पास लगेंगे: आपके घंटे के ब्लॉक की विभिन्न कॉलम चौड़ाई को समझने वाला पहला पास, पंक्तियों को आकर्षित करने के लिए उस जानकारी का उपयोग करने वाला दूसरा।

1

मैं पूरी तरह से यकीन नहीं है, लेकिन मुझे लगता है कि तुम क्या चाहते है: अलग पंक्तियों में एक ही शुरू करने का समय है कि पर

  • विस्थापन सिंक्रनाइज़ किए जाते हैं, यानी एक ही क्षैतिज स्थिति है (पहले विस्थापन प्रत्येक पंक्ति अन्य पंक्तियों पर पहले विस्थापन) के साथ सिंक्रनाइज़ है पर
  • "असली" घटनाओं और अंतराल में एक ही शुरू करने का समय है कि सिंक्रनाइज़ किए जाते हैं, और एक ही शुरुआती समय के साथ विस्थापन के बाद आते हैं
  • की एक घटना की चौड़ाई (और संभवतः अपने विस्थापन) उसकी अवधि पर निर्भर करता है, लेकिन अन्य पंक्तियों पर विस्थापन पर नहीं, यानी समाप्त होने के समय सिंक्रनाइज़ नहीं कर रहे हैं

आप बार समाप्त होने चाहते हैं सिंक्रनाइज़ किए जाने की , आपको समझाना होगा कि कैसे; लेकिन मुझे कोई स्पष्ट तरीका नहीं दिख रहा है।

फिर

आप प्राप्त निम्नलिखित अपने मूल समस्या के लिए समाधान (राजधानियों = घटनाओं, छोटे अक्षरों = विस्थापन, डॉट्स = अंतराल, अंतरिक्ष = "तुल्यकालन के लिए इंतज़ार कर", संख्या शुरू कर रहे हैं बार घटनाओं की):

0 123 4 567 
AbC.D .e FG 
A B.CcD EF 
A BCD EfgHI 

आप देख सकते हैं कि समाप्त होने के समय निम्न उदाहरण में सिंक्रनाइज़ नहीं कर रहे हैं:

0 12 
AAa 
Aa B 
AaaB 

और एक बड़ा यादृच्छिक उदाहरण:

      11 11 1 1  1  1 1 1 22 22 2  2 22 22 33 333 3 3 3 3 3 4 44444 4 4 4 45 
    01 2 34 5678 9 01 23 4 5  6  7 8 9 01 23 4  5 67 89 01 234 5 6 7 8 9 0 12345 6 7 8 90 
    AAAA BB CCC dd.. EEe Fff..  GGGGGg   ....   ... HHH ....  IIii JJJ  ... KKK LLLLl 
abbbCCC DDDDDdd ..  EEEEE  Fff GGG   HHH IIIii  JJJjj KKKK  LLLl Mno. PPP qR SSSSSs TT uuuVV 
    ... AAAAA BBB  CC DDDD    ...  EE FFFF   GHhhIIII  JJ. K Lll.m....  NNNO .... 
    ......  AAAA  .. ....  BBB   CCCCCc  DDDDDd  Ee FFFFff G hhhIIIII   JJJ KLLLLLll  M 
    .. AAA BBBCcc DD EE .. FFF   gH IIIIIi  J  KKk LL MMMMM  NNNNNn   OOo PPQQQQ rrr... 
    AAAAa . BBBBbb CCCCC  DDDDDd   eeeFFFFF  GG  HH .....  IIIII   JJ K LM.NNNNN   . 
    AAAaaBBB CCCcc DDDDDdd  EeFF   ...  GGgHHHH   III JJJJ  KKK llMMMm nnnOOOO PPPp ...  Q 
    AAAAA  BBBBB  CCCC  .....    DDD EEEEE   FFFff .... GGGG   HHHHhh  II....  j . . 
    AAAaa.. BBBBbb CccDDDDD  ....    EEE .F GgghhhII Jj KKKK  ... ...  LLll ... MMMM  N OooP 
    .... Aa ..BCCC  .....   DDD   EEEe FFf .....   GGGG  HIIIIIii   . JJ .... KKk  LL 
    AAAAAa bbC.....  DDDDD   ....   eeFFFFff GGGGG   ... hh IIJJJ  KKK  L MMMMMmmNNNN 
    ..aBBB CCCCc .....  .....    ... D. E  FFFFFff ggHHhiiiJKKKk  LLLLL  mmmNNNOP Q RRR 
    AA BbCCCC DD Ee FFFFFff  GGGGG     HH IIIi  JjjK.. LLLll  MMMMmm ....  . NNNOOOOOoo  P 
    AB CCCCC .....  ddEEEE  fffGgg HHHHHhh  II jjKKKK   LLLL  MMMM nn.. OO PPPPPpp QQQQQqq 
    AAA BBB CCCC  DDdd EE FFF  gggHh IIIii JJJJ   K LLLLl MMm NNOOOO   . PP .QQQRRRRR 

और अब कोड (खेद है कि यह बहुत लंबा है, रोचक भाग के लिए Timetable.__init__ देखें, बाकी ज्यादातर सुंदर प्रिंटिंग है)।

from heapq import merge 
from itertools import groupby, cycle, chain 
from collections import defaultdict 
from operator import attrgetter 
from string import ascii_uppercase 

# events are processed in this order: 
# increasing start time, displacements (duration=0) first, and grouped by row_id 
ev_sort_attrs = attrgetter("time", "duration", "row_id") 


class Event: 

    def __init__(self, duration, displacement=0, visible=True, time=None, row_id=None): 
     self.duration = duration 
     self.displacement = displacement 
     self.visible = visible 
     self.time = time 
     self.row_id = row_id 
     self.pos = None 

    def draw(self, char): 
     return char * self.duration + char.lower() * self.displacement 

    def __lt__(self, other): 
     return ev_sort_attrs(self) < ev_sort_attrs(other) 


def Gap(duration): 
    return Event(duration, visible=False) 


class Timetable(list): 
    def __init__(self, *args): 
     """ compute positions for a list of rows of events """ 
     list.__init__(self, *args) 

     # compute times for the events, and give them row_ids 
     for i, row in enumerate(self): 
      t = 0 
      for ev in row: 
       ev.time = t 
       t += ev.duration 
       ev.row_id = i 

     # map times to position for displacements and event 
     t2pos_disp = defaultdict(int) # maps times to position of synchronized start of displacements 
     t2pos_ev = defaultdict(int) # maps times to position of synchronized start of events and gaps 

     # the real work is done in the following loop 
     t_prev = 0 
     for t, g in groupby(merge(*self), key=attrgetter("time")): 

      # different times should have a minimum distance corresponding to their difference 
      t2pos_ev[t] = t2pos_disp[t] = max(t2pos_ev[t], t2pos_ev[t_prev] + t - t_prev) 
      t_prev = t 

      for (duration, row_id), g_row in groupby(g, key=attrgetter("duration", "row_id")): # process all displacements first, then the events 
       pos_ev = t2pos_ev[t] if duration > 0 else t2pos_disp[t] # events and displacements start at different 
       for ev in g_row: 
        ev.pos = pos_ev 
        pos_ev += ev.duration + ev.displacement 
       t2pos_ev[t + ev.duration] = max(t2pos_ev[t + ev.duration], pos_ev) 

     # keep our results... 
     self.t2pos_ev = t2pos_ev 
     self.t2pos_disp = t2pos_disp 


    @staticmethod 
    def str_row(row): 
     """ draw row, uppercase letters for real events, lower case letters for 
     displacements, dots for gaps""" 

     ev_chars = cycle(ascii_uppercase) 
     out = [] 
     l = 0 
     for ev in row: 
      if ev.pos > l: 
       out.append(" " * (ev.pos - l)) 
      out.append(ev.draw(next(ev_chars) if ev.visible else ".")) 
      l = ev.pos + len(out[-1]) 
     return "".join(out) 

    def __str__(self): 
     max_t, max_p = max(self.t2pos_ev.items()) 
     w = len(str(max_t)) 
     header_temp = [" " * w] * (max_p + 1) 
     for t, p in self.t2pos_ev.items(): 
      header_temp[p] = "%*d" % (w, t) 
     headers = ("".join(header) for header in zip(*header_temp)) 

     rows = (self.str_row(row) for row in self) 

     return "\n".join(chain(headers, rows)) 


if __name__ == "__main__": 
    # original example 
    row_one = [Event(1), Event(0,1), Event(1), Gap(1), Event(1), Gap(1), Event(0,1), Event(1), Event(1)] 
    row_two = [Event(1), Event(1), Gap(1), Event(1, 1), Event(1), Event(1), Event(1)] 
    row_thr = [Event(1), Event(1), Event(1), Event(1), Event(1), Event(0,1), Event(0,1), Event(1), Event(1)] 

    timetable = Timetable([row_one, row_two, row_thr]) 
    print(timetable) 

    print("-" * 80) 

    # short example, shows ending times are not synchronized 
    print(Timetable([[Event(2, 1)], [Event(1, 1), Event(1)], [Event(1, 2), Event(1)]])) 

    print("-" * 80) 

    # larger random example 
    def random_row(l): 
     import random 
     res = [] 
     t = 0 
     while t < l: 
      x = random.random() 
      if x < 0.1: res.append(Event(0, random.randint(1, 3))) 
      elif x < 0.8: res.append(Event(min(random.randint(1, 5), l - t), random.randint(0, 1) * random.randint(0, 2))) 
      else: res.append(Gap(min(random.randint(1, 5), l - t))) 
      t += res[-1].duration 
     return res 

    print(Timetable([random_row(50) for _ in range(15)])) 
-1

मैं घटना के लिए एक आइकन और अवधि के लिए एक बार का उपयोग करने की सलाह देता हूं।