2014-05-31

Revit Takvimi

redhotbim.com adresinden ingilizce blog yazmaya başladım. (Uzuun seneler sonra geri döndüm de diyebilirim)
Yeni blog'a örnek bir takvim family'si koydum. Biraz da açıkladım.

D_GEN_CALENDAR.rfa (Revit 2015)

Bu family'nin hikayesi şöyle. LOD 350-400'e gelmeden 300 ve hatta 200'de donatı datası ve hatta hesabı gerekmekte. Bu ihtiyacın çözümünü Revit platformuna taşımak gerektiğini düşündüm.
Bir iki hafta gömüldüm önce BS 8666:2005 ten pratik uygulamalara, CAD standartlarından şirket standartlarına, klasik hesap yöntemlerinden ustalıkla otome edilmiş şirket uygulamasına konuyu anlamaya çalıştım.
(Sağolsunlar Ressam ve Mühendis iş arkadaşlarım hiçbir sorumu yanıtsız bırakmadılar).
Sonra da oturdum Revit için bir aplikasyon yazdım. İşin bittiği gün eve geldim baktım kafada hala hesap kitap dolanıyor, hah dedim kafayı dağıtmak için Light ve değişik birşey yapmak lazım.
Takvim böyle çıktı..(Evet family'nin adında imla hatası yapmışım.. Artık öyle kabul ediverin bir daha bir daha yükleyemeyeceğim!)


Takvim family'sinin 3 tane veri giriş parametresi var. Day, Month, Year. Day parametresi sıfır girilirse aşağıdaki gibi aylık takvimi gösteriyor.


Oğluşumun doğum günü gibi güzel bir tarih girerseniz başlığa günün adını yazıyor ve günü işaretliyor.


DRV (driving / düzeltici) parametreleri olmasına rağmen, negatiflerle uğraşacak vaktim olmadığı için belli bir aralıkta yapmayı tercih ettim:

dayDRV= 0 /  o ayın maksimum gün sayısı
monthDRV = 1 / 12
yearDRV =2 / ...

Karşılaştığım problemler ve çözümlerim.

ARTIK YIL (Leap Yes/No Parameter)

Artık yılı çözmem gerekiyordu. Nette ararken wikipedia'da şuna rastladım:

eğer yıl 4e bölünemiyorsa --> normal yıl
değilse eğer yıl 100e bölünemiyorsa --> artık yıl
değilse eğer yıl 400e bölünemiyorsa --> normal yıl
değilse artık yıl

Revit'te aşağıdaki gibi yazdım:

if(not(yearDRV / 4 = rounddown(yearDRV / 4)), 1 = 0, if(not(yearDRV / 100 = rounddown(yearDRV / 100)), 1 = 1, if(yearDRV / 400 = rounddown(yearDRV / 400), 1 = 1, 1 = 0)))

Revit'in modulo operatörü yok. (Bölme işleminde artanı bulma.) Ama rounddown ile bir numara çekerek mod x = 0 bulunabilir.

yearDRV / 4 = rounddown(yearDRV / 4)

Bir değer dörde tam bölünüyorsa aynı değerin rounddown'ına eşit olmalıdır. Bunu yakaladıktan sonra gerisi sadece if ve not'lar ile algoritmayı yazmak oldu..

AYIN İLK GÜNÜ HANGİ GÜN?

Takvime başlayabilmek için ayın ilk gününün yerini bulmam gerekiyordu. Neyseki wikipedia'da konuyla ilgili bir sayfa buldum.

Tablolu yöntemlerle yapmak çok havalı olurdu aslında! Fakat bir Cuma gecesi 1-2 saatlik sürede bitmez diye Saf(?) Matematiksel yöntemlerden birini seçmem gerekiyordu. Ben de Zeller's Congruence algoritmasını seçtim.


h haftanın günü (0 = Saturday, 1 = Sunday, 2 = Monday, ...)
q ayın günü ( Benim aradığım FirstDay = 1)
m ay (3 = March, 4 = April, 5 = May, ..., 14 = February)
K yüzyılın yılı (yıl mod 100).
J yüzyıl (Gerçek anlamda değil basamaksal olarak. Yani 1995 20. yy değil 19. yy olarak giriliyor.)

Formül matematikçilerin modulo bölmesi tarifine dayanıyor. -2 mod 7 =5
Fakat pekçok bilgisayar dili sonucu -2 verecektir. Bunu düzeltmenin en basit yolu formülde − 2J'i + 5J ile değiştirmek:


Zeller aritmetik kullandığı için yılı J ve K olarak ikiye bölmekte sıkıntı görmedi. Ve yine bilgisayarlarda tek bir Y yıl ile yazmak daha uygun:


Ee formül bu hale geldikten sonra Revit'te kolaylıkla yazılır: (zellerHdayFirst Integer Parameter)

FirstDay + rounddown(((if(monthDRV = 1, 13, if(monthDRV = 2, 14, monthDRV))) + 1) * 2.6) + yearDRV + rounddown(yearDRV / 4) + (6 * rounddown(yearDRV / 100)) + rounddown(yearDRV / 400) - (7 * rounddown((FirstDay + rounddown(((if(monthDRV = 1, 13, if(monthDRV = 2, 14, monthDRV))) + 1) * 2.6) + yearDRV + rounddown(yearDRV / 4) + (6 * rounddown(yearDRV / 100)) + rounddown(yearDRV / 400)) / 7))

MATRİS


Matriste iki çeşit Label'ım var. (Bazıları üst üste geçmiş durumda):

DAYS ve GRAYS

DAYS bize gereken ayın günleri.. GRAYS önceki ve sonraki ayları gösteren dekoratif olanlar..

Zeller Algoritması haftaya Cumartesi ile başlıyor ve buna 0 değeri veriyor. (0 = Saturday, 1 = Sunday, 2 = Monday, ...)
Ben de Matriste aynını yaptım. Yani d32 demek:

d = DAYS Label'ı
3 =  Üçüncü sıra
2 = Zeller Günü iki, yani Pazartesi

Dikkat ederseniz ilk grup GRAYS g12'den g10'a kadar. Çünkü bir ayın başlayabileceği haftanın en son günü Pazar (d11). GRAYS bu günden önce bitmeli.
Bu grup önceki ayın son günlerini gösterdiği için, önceki ayın kaç çektiğini bulmam gerekiyor.

cntDAYSlast (Integer Parameter)

if(or(monthDRVlast = 1, monthDRVlast = 3, monthDRVlast = 5, monthDRVlast = 7, monthDRVlast = 8, monthDRVlast = 10, monthDRVlast = 12), 31, if(or(monthDRVlast = 4, monthDRVlast = 6, monthDRVlast = 9, monthDRVlast = 11), 30, if(Leap, 29, 28)))

Yani diyor ki eğer geçen ay
1,3,5,7,8,10,12 -ise> 31 gün
değilse ve eğer
4,6,9,11 -ise> 30 gün
değilse ve eğer
Artık Yıl -ise> 29
yok hiçbiri değilse :) 28

g12'den g10'a Label'lar bu ayın ilk gününden bir gün önceden tablonun başına doğru ters yönde, geçen ayın son gününden aşağıya sayıyor.g12v'den g10v'ye parametreler de visibility'sini kontrol ediyor.

DAYS

Zeller ilk gününü biliyoruz. (zellerHdayFirst)
Bu ayın kaç gün olduğunu da. (cntDAYS).
E sayıyoruz o zaman. (Aslında o kadar basit değil. Family'yi inceleyin bakın bakalım beğenecek misiniz?
Visibility'lere çok iş bırakmamak için algoritmik sonuçlara yürüdüm.)

İkinci bölüm GRAYS (g52 to g61) bu ayın sonundan başlayıp düz sayıyor. g52'den başlıyor çünkü bu ay en erken Pazartesi (d12) başlayabilir ve en kısa 28 gün olabilir.

SEÇİLEN TARİH

Aslında seçilen tarih için tüm matriste işaretlerim olup bunları visibility ile kapatıp açabilirdim. Bu bana daha çok imkan tanırdı. Ama o saatte 37 tane daha parametre yazmak içimden gelmedi :)
Ben de bir tane işaret Family'si koydum bildiğin revit ölçüleriyle istediğim yere sürüdüm :)

zellerHdaySelected (Integer Parameter) Seçilen günün Zeller gününü buluyor
todayKX (Integer Parameter) k Kolon çarpanı
todayKY (Integer Parameter) k Sıra çarpanı
todayX (Length Parameter) X yönünde mesafe
todayY (Length Parameter) Y yönünde mesafe


Hiç yorum yok:

Yorum Gönderme