2011-12-09 14 views
13

Đây là câu hỏi về tạo hình ảnh hoặc bất kỳ đại diện nào khác cho một tập hợp song song dữ liệu. Không phải là về vẽ hoặc lập trình GUI nhưng tính toán vị trí. Đầu tiên tôi sẽ giải thích một chút nơi tôi đứng ngay bây giờ và hình ảnh thứ hai và ví dụ cho thấy vấn đề của tôi.Tạo biểu diễn tuyến tính, dựa trên dòng thời gian từ các mục tiêu tốn thời gian và các mục không, nhưng vẫn cần không gian để vẽ trên

Trạng thái hiện

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

tôi có các đối tượng một chiều nhưng họ được liên kết bằng cách đặt chúng trên song song "dòng". Hãy gọi các đối tượng "sự kiện" một chiều này có "Thời lượng" là một đơn vị thời gian. Những sự kiện này có một biến thể không có gì xảy ra, các đối tượng không có dữ liệu nhưng có thời lượng; Một "khoảng cách" -object.

Vì vậy, chúng tôi nhận được một thời gian biểu với các đối tượng simulatanious bao gồm các sự kiện và khoảng trống, đó là khá dễ dàng để xử lý như ba danh sách các đối tượng. Hình ảnh cũng đơn giản: Lặp qua danh sách và vẽ từng đối tượng theo thời lượng của nó.

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.  

Vấn đề

Bây giờ đến vấn đề này. Có những đối tượng cần một không gian đồ họa nhưng có thời lượng bằng không. Tôi gọi đây là "Displacement".

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

Hoặc chúng ta cần đối tượng có thời gian mà còn có dịch chuyển. Điều này vẫn không phải là vấn đề khi chúng tôi chỉ có một hàng duy nhất, nhưng việc đồng bộ hóa các hàng phức tạp hơn và tôi không có giải pháp cho việc này.

Trong hình ở trên, các khối màu đỏ có thời lượng bằng 0 và được di dời. Các khối màu xanh có thời gian và cũng bị dịch chuyển.

Ví dụ: * Hãy tưởng tượng thời gian biểu cho hội nghị với khe loa khác nhau mỗi giờ (khoảng thời gian của chúng tôi). Mỗi hàng đại diện cho một phòng hội nghị khác nhau.

  • Các khối màu đen là các bài phát biểu và có thể có một chủ đề ngắn được viết bên trong chúng (đồ họa).

  • Khối màu xanh cũng là bài phát biểu, nhưng chủ đề quá dài để viết nên chúng tôi cần thêm không gian một lần.

  • Màu đỏ là các ghi chú như thay đổi số phòng. Họ không mất thời gian của riêng họ nhưng liên quan đến tất cả các mục mà đến sau họ. *

Nhiệm vụ là tìm cách để tính toán pixelcounter từ chức năng ở trên để nó đúng cho mỗi hàng một mình nhưng cũng là sự dịch chuyển trong một hàng ảnh hưởng đến tất cả các hàng khác và tạo thêm không gian ở đó. Mục tiêu là thời lượng được cố định và căn chỉnh trong mỗi hàng. Bất kỳ sự kiện hoặc khoảng cách nào cần bắt đầu, ví dụ, đơn vị đếm 4, sẽ bắt đầu ở cùng một vị trí tuyệt đối.Điều này có nghĩa là bất kỳ đối tượng không có thời gian/chuyển vị trí nào bắt đầu tại một điểm thực trong thời gian/thời lượng nhưng không tiêu thụ bất kỳ thời gian/khoảng thời gian nào để tất cả các mục tiếp theo bắt đầu trên cùng một khoảng thời gian cho đến khi sự kiện thời gian thực tiếp theo là bao gồm. Từ một quan điểm khác cũng có nghĩa là các mục thời lượng không bắt đầu luôn trước các sự kiện có thời lượng.

Trong hình, chúng ta có thể thấy một trường hợp khá đơn giản trong cột 2, điều này cũng có nghĩa là điều này bắt đầu khe thời gian thứ hai. Mặc dù có ba sự kiện thực sự trong cột đó được dịch chuyển sang bên phải bởi vì một mục thay thế ở đó. Cột 4 có một mục thời gian có chuyển vị là tốt. Một lần nữa, tất cả các mục bắt đầu trong khe 5 được dịch chuyển sang phải. Colum 6 là điều thú vị nhất và vấn đề thực sự của tôi, tôi không thể tìm thấy giải pháp ở đây. Một lần nữa, tất cả các sự kiện thực sự trong cột 6 được chuyển sang bên phải và vẫn bắt đầu cùng một lúc. Nhưng ở đây chúng ta có a) Displacement-Objects trong hai hàng và hai b) hai đối tượng ngay phía sau nhau. Vì vậy, điều quan trọng là các sự kiện thực sự phải biết chuyển hoàn toàn nhưng cũng quan trọng đối với đối tượng thứ hai ở hàng thứ ba để biết rằng có thêm một vật chuyển vị trước đó.

Cảnh báo: Biểu diễn đồ họa có thể đề xuất phương pháp dựa trên bảng trong đó mỗi cột có chiều rộng riêng. Nhưng đây là nơi mà ví dụ này kết thúc. Các ứng dụng thực sự giao dịch với thời gian phổ biến là 300-10.000 cho mỗi sự kiện nhưng thời lượng của 1 là khó nhưng về mặt kỹ thuật có thể. Vì vậy, bảng sẽ có chiều rộng cột của một thời lượng. Xem xét chúng tôi đã đi vào hàng trăm ngàn thời gian hoàn thành (lần số hàng) điều này có thể kéo xuống hiệu suất.

Dữ liệu của ảnh này sẽ trông như thế này. Làm thế nào tôi có thể vẽ hình ảnh thứ hai với dữ liệu này? Hoặc những gì cần phải được thay đổi, tôi mở cho tất cả các đề xuất.

Cảm ơn bạn rất nhiều vì đã dành thời gian và sự quan tâm của bạn. Nếu bạn không biết một giải pháp, xin đừng ngần ngại hỏi tôi những câu hỏi hoặc cho tôi thấy những sai lầm trong quan điểm của tôi, nó cũng sẽ giúp tôi suy nghĩ.

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

Vâng, trước tiên, bạn có chắc chắn bạn phải có không gian cho họ? Bạn có thể vẽ chúng khác nhau, thay vì các thanh thời gian có một số cách khác để hiển thị chúng. –

+0

Đáng buồn thay, có, tôi cần tất cả chúng trên một hàng. – nilsge

+0

Cho tất cả các đối tượng có số hàng, chiều rộng và chiều rộng đồ họa: bạn sẽ cần phải tìm các vị trí đồ họa cho từng đối tượng, sao cho tất cả các hàng đều phù hợp với đồ họa (không có chồng chéo) và tất cả các lần bắt đầu giống nhau Chức vụ. Đúng không? – Ishtar

Trả lời

0

Bạn cần có chức năng ánh xạ thời gian của bạn đến tọa độ x. Phần khó khăn là, đôi khi bạn cần thêm không gian tại một thời điểm. Điều này có thể được giải quyết với một danh sách các đối tượng, nói khi nào và bao nhiêu không gian là cần thiết.

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

Bất cứ khi nào bạn cố gắng đặt một đối tượng, và nhận thấy không có đủ chỗ (vì các yếu tố chồng chéo lên nhau), chỉ cần chèn một số không gian hơn tại thời điểm mong muốn, extraSpaceList.add({when=2s,space=4pixels}). Xử lý tất cả các hàng một, và sau đó tất cả chúng một lần nữa cho vị trí cuối cùng.

Điều này sẽ dễ dàng hơn nếu bạn chuyển đổi các đối tượng của mình để có thời gian bắt đầu và kích thước đồ họa. Sau đó, không có sự khác biệt giữa Gap và Event.

0

Nếu tôi hiểu câu hỏi của bạn ...

Đối với mỗi cột, theo dõi chiều rộng tối đa của các hàng hộp zero-thời gian như bạn đang làm một xử lý sơ bộ mỗi hàng. Khi bạn cuối cùng vẽ từng sự kiện thực, sự kiện đó sẽ bắt đầu ở cuối giá trị độ rộng tối đa cho cột của nó. (Tôi giả sử bạn đã tính toán vị trí bắt đầu của cột.)

Trong biểu đồ đầy màu sắc ở trên, xử lý hàng 1 sẽ cung cấp cho bạn độ rộng tối đa bằng 0 (ví dụ) [0, 10, 0, 0, 0, 10, 0]. Hàng 2 sẽ không thay đổi nó. Hàng 3 sẽ đổi thành [0, 10, 0, 0, 0, 20, 0].

Khi bạn vẽ một sự kiện thực, sự kiện sẽ bắt đầu ở cột + cột tối đa không có thời lượng của cột_start +.

0

Tôi thấy một vài vấn đề với mã Sự kiện của bạn vì nó đứng: 1) không có cách nào để cho biết bao nhiêu khoảng trống để phân bổ cho chuyển vị trí, cho dù sự kiện có thời lượng bằng 0 hay không; 2) nếu bạn có (nói trong hàng bốn) một sự kiện mà có 3 đơn vị và bắt đầu từ 5, nó sẽ được hoàn toàn rút ra trong 5 và 6 khe mà không bao giờ nhận được đến 7.

Tôi nghi ngờ bạn sẽ cần một cái gì đó như:

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 

Nếu không xử lý biểu đồ dưới dạng bảng, tôi không chắc chắn cách giải quyết vấn đề thứ hai tôi nêu ở trên.

Ngoài ra, nó sẽ lấy hai vé: thẻ đầu tiên để tìm ra chiều rộng cột khác nhau của các khối giờ của bạn, giây để sử dụng thông tin đó để vẽ các hàng.

1

Tôi không hoàn toàn chắc chắn, nhưng tôi nghĩ rằng những gì bạn muốn là:

  • chuyển vị trên các hàng khác nhau mà có cùng thời gian bắt đầu được đồng bộ hóa, tức là có vị trí ngang nhau (sự dịch chuyển đầu tiên trên mỗi hàng được đồng bộ với chuyển vị đầu tiên trên các hàng khác)
  • sự kiện "thật" và những khoảng trống có cùng thời gian bắt đầu được đồng bộ hóa, và đến sau khi chuyển vị với thời gian khởi động cùng
  • chiều rộng của một sự kiện phụ thuộc vào thời gian của nó (và có thể dịch chuyển của nó), nhưng không trên chuyển vị trên các hàng khác, tức là lần kết thúc chưa đồng bộ

Nếu bạn muốn kết thúc thời gian được đồng bộ , bạn phải giải thích như thế nào; nhưng tôi không thấy rõ ràng.

Sau đó, bạn sẽ có được sau giải pháp cho vấn đề ban đầu của bạn (thủ đô = sự kiện, chữ thường = chuyển vị, chấm = khoảng trống, không gian = "chờ đợi đồng bộ hóa", con số này được bắt đầu từ thời điểm sự kiện):

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

Bạn có thể thấy rằng thời gian kết thúc chưa đồng bộ trong ví dụ sau:

0 12 
AAa 
Aa B 
AaaB 

Và một ví dụ ngẫu nhiên lớn hơn:

      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 

Và bây giờ mã (xin lỗi quá lâu, hãy xem Timetable.__init__ cho phần thú vị, phần còn lại chủ yếu là in đẹp).

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

Tôi khuyên bạn nên sử dụng biểu tượng cho sự kiện và thanh cho thời lượng.