pencere-yerlesimi
by Cihad Paksoy
mimarikat-planipencereduvarblok
Description
Kat planındaki duvarlara pencere yerleştirir — duvarı kırıp boşluk açar, kenarları kapatır ve pencere bloğunu boşluğa oturtur. Blok tanımını çizimden bulur, genişliğini ÖLÇER, dönme/aynalamayı tek örnekle doğruladıktan sonra kalanını batch yapar. "Pencereleri çiz", "bu cepheye pencere koy" dendiğinde kullan.
Example prompts
- /pencere-yerlesimi İşaretlediğim bölgedeki her mahale bir pencere çiz.
- /pencere-yerlesimi Bu dairenin güney cephesine pencere koy.
- /pencere-yerlesimi Odalara, çizimde zaten tanımlı olan pencere bloğunu kullanarak pencere ekle.
- /pencere-yerlesimi Salon ile balkon arasına balkon kapısı yerleştir.
Full content
---
name: pencere-yerlesimi
description: Kat planındaki duvarlara pencere yerleştirir — duvarı kırıp boşluk açar, kenarları kapatır ve pencere bloğunu boşluğa oturtur. Blok tanımını çizimden bulur, genişliğini ÖLÇER, dönme/aynalamayı tek örnekle doğruladıktan sonra kalanını batch yapar. "Pencereleri çiz", "bu cepheye pencere koy" dendiğinde kullan.
tags: [mimari, kat-plani, pencere, duvar, blok]
---
Pencere yerleştirmek **tek bir blok yerleştirme işi değildir**. Duvar kesintisiz çiziliyse
bloğu üstüne koymak yanlıştır: gerçek çizimde duvar kırılır, boşluk açılır, kenarlar kapatılır
ve blok o boşluğa oturur. Aşağıdaki akış bunu üretir.
Bu bir **yazma** işidir: önizleme → onay → commit zinciri geçerlidir.
## Örnek prompt'lar
- "İşaretlediğim bölgedeki her mahale bir pencere çiz."
- "Bu dairenin güney cephesine pencere koy."
- "Odalara, çizimde zaten tanımlı olan pencere bloğunu kullanarak pencere ekle."
- "Salon ile balkon arasına balkon kapısı yerleştir."
## Kapsam: "işaretlediğim bölge" nerede?
Kullanıcı bir alana işaret ettiğinde (`işaretlediğim/seçtiğim bölge`, `şurada`) kapsamı KENDİN
uydurma, iki kaynaktan biri vardır:
1. Mesaja **iliştirilmiş** bir bölge (panel'deki region chip'i, etiketinde bbox yazar) —
varsa önceliklidir.
2. Yoksa kullanıcı AutoCAD'de **CIZGENREGION** komutuyla işaretlemiş olabilir: `get_marked_region`
çağır, dönen bbox işin kapsamıdır.
Hiçbiri yoksa kullanıcıya CIZGENREGION'ı çalıştırmasını söyle. Zaten gösterdiği yeri yeniden
seçtirme.
## Bir pencerenin anatomisi
Çift çizgili bir duvarda pencere şu dört şeyden oluşur:
1. **Dış yüz çizgisi** boşluğun iki ucundan kırılır (iki parça kalır).
2. **İç yüz çizgisi** AYNI iki koordinattan kırılır.
3. Boşluğun iki ucuna, duvar kalınlığı boyunca birer **kenar çizgisi** (jamb) çizilir —
duvarla aynı katmanda. Bunlar olmazsa duvar açık ağızlı görünür.
4. **Blok** boşluğa oturur; çıkıntılı parçaları (denizlik, balkon döşemesi) DIŞARI bakar.
**Boşluk, bloğun bbox genişliği DEĞİLDİR.** Pencere kasası çoğu zaman duvara biner: bloğun
kutusu boşluktan her iki yanda birkaç birim geniş olur. Binme miktarı ofisten ofise, hatta
blokan bloğa değişir — kimi blokta sıfırdır. Bbox'ı boşluk sanarsan duvarı fazla kırarsın.
Doğru boşluğu şöyle bul, bu sırayla:
1. **Yerine oturmuş mevcut bir örnekten ölç** (en güvenilir): çizimde o bloğun duvara oturmuş
bir örneği varsa, çevresindeki kırık duvar çizgilerinin arasındaki AÇIKLIĞI ölç. Bloğun
kutusuyla bu açıklık arasındaki farkı (kasa binmesi) hesapla ve aynı farkı uygula. Binmeyi
her blok için AYRI ölç — aynı çizimde farklı çıkabilir.
2. **Blok adı** çoğu ofiste nominal boşluğu taşır — 1. adımı doğrulamak için çapraz kontrol
olarak kullan.
3. İkisi de yoksa kullanıcıya sor. Bbox'ı boşluk olarak KULLANMA.
## Akış
### 1. Bloğu bul — sıfırdan çizmek SON çaredir
`get_overview`'un `block_names` listesine bak. Öncelik sırası:
1. **Çizimde zaten tanımlı bir pencere bloğu** varsa onu kullan (`insert_blocks`). Çoğu proje
dosyasında vardır — kullanıcının ofis standardı odur, en doğrusu budur.
2. Yoksa ve çizimde örnek bir pencere geometrisi varsa, `define_block(source_handles)` ile
**kayıpsız klonla**.
3. Kullanıcının kataloğu varsa oradan al.
4. Hiçbiri yoksa kullanıcıya SOR — hangi pencereyi istediğini, genişliğini. Kendin bir pencere
çizmek en son seçenektir ve çizdiğini beyan et.
Birden çok aday blok varsa (farklı genişlikler, balkon kapısı vs. pencere) kullanıcıya hangisini
nerede istediğini sor ya da mahal tipine göre seç ve **beyan et**.
### 1c. Pencere blokları ANONİM olabilir — ada göre eleme yapma
AutoCAD'de kopyalanmış/patlatılmış-yeniden-bloklanmış tanımlar `A$C…` gibi anonim adlar taşır.
Gerçek bir projede pencerelerin bir kısmı anlamlı adlı (ör. genişliğini taşıyan bir ad), bir
kısmı `A$C…` biçiminde anonim olabilir — adına bakıp elersen pencerelerin yarısını kaçırırsın.
Pencere adaylarını **kullanımlarından** tanı, adlarından değil:
- Blok örneği bir duvar boşluğuna oturmuş mu (çevresinde kırık duvar çizgileri var mı)?
- Aynı **derinliği** paylaşan bloklar aynı ailedendir: bir pencere ailesinde derinlik duvar
kalınlığına bağlı olduğu için sabit kalır, genişlik değişir. Blok kutularını derinliğe göre
grupla — tek bir derinlikte toplanan farklı genişlikler tek ailedir.
- Katman ipucu olabilir ama tek başına yetmez; aynı çizimde pencereler birden çok katmana
dağılmış olabilir.
Bulduğun aileyi genişliklerine göre listele; hangi genişliğin hangi mahal tipinde kullanıldığını
mevcut bir plandan oku (ör. salonda geniş, ıslak hacimde dar) ve bunu **beyan et**.
**Aile TEK bir DİNAMİK blok da olabilir.** Bu durumda farklı genişlikler ayrı blok adları değil,
aynı bloğun parametre değerleridir. `get_entities` bir örnek üzerinde `dynamic_properties`
(parametre → şu anki değer), `dynamic_property_choices` (kabul edilen değerler) ve
`dynamic_readonly` döner; statik blokta bu alanlar hiç çıkmaz. Blok adına bakıp "tek genişlik
var" diye karar verme — önce bir örneğin dinamik parametrelerini oku. Varyantları
`dynamic_property_choices`'tan listele ve hangisini nerede kullandığını beyan et.
### 1d. Çizimde ÇÖZÜLMÜŞ bir kopya var mı?
Proje dosyalarında aynı planın birden çok kopyası bulunabilir: biri ham, biri pencereleri
yerleştirilmiş (başka bir kat, bir önceki revizyon, ölçülendirilmiş pafta). Varsa bu en değerli
kaynaktır — pencere yerleri, blok seçimi ve dönmeler zaten o ofisin kararıdır; sen bulmaya
çalışma, **kopyala**.
Nasıl bulunur: mahal adlarını oku, aynı ad dizisinin ikinci bir kümede tekrarlandığını gör,
iki küme arasındaki sabit ötelemeyi (Δx, Δy) hesapla. Duvar geometrisi öteleme dışında
örtüşüyorsa aynı plandır.
Nasıl kullanılır: çözülmüş kopyanın duvar çizgilerini öteleyip ham planınkiyle **farkını** al.
Fark tam olarak pencere işidir: silinecek kesintisiz çizgiler + çizilecek parçalar ve kenarlar.
Bloklar için de aynı ötelemeyi uygula.
**Bunu kullandıysan BEYAN ET** — sonuç bir türetme değil, bir kopyadır. Ayrıca kapanışı sayıyla
doğrula: `ham çizgi sayısı − silinen + eklenen = çözülmüş kopyanın çizgi sayısı`. Tutmuyorsa
fark eksik çıkarılmıştır.
Çözülmüş kopya YOKSA aşağıdaki adımlar zaten tam yolu veriyor; bu kısayol bir kolaylık, ön
koşul değil.
### 2. Bloğun ölçülerini ÖLÇ — adına GÜVENME
Gerçek ölçü:
- Çizimde bloğun bir örneği varsa: `cad.query` ile handle'ını al → `cad.entities([handle])` →
`bbox: {min:[x,y], max:[x,y]}` → genişlik = `max[0] - min[0]` (blok döndürülmüşse yüksekliğe
bak). **Bu KASA ölçüsüdür, boşluk değil** — boşluk için yukarıdaki anatomi bölümüne dön.
- **Dinamik blokta ölçtüğün, yalnız O ÖRNEĞİN varyantıdır.** Aynı blok başka bir parametre
değeriyle başka genişlik verir; kullanacağın her varyantı ayrı ölç (bir tane yerleştir,
bbox'ını oku, sil).
- Örnek yoksa: boş bir alana bir tane yerleştir, bbox'ını oku, işin bitince sil.
Ölçtüğün kasa genişliğini ve türettiğin boşluğu **ayrı ayrı beyan et** — "blok kutusu ⟨K⟩,
duvardaki boşluk ⟨B⟩, kasa iki yana ⟨(K−B)/2⟩ biniyor".
### 3. Duvarı ve boşluğun yerini belirle
**Önce hangi mahalin cephesi olduğunu çıkar.** "Her mahale pencere" isteği harfi harfine
uygulanamaz: bir kat planında mahallerin yarısı iç mahaldir (antre, hol, vestiyer, banyo, duş,
asansör, ışıklık, şaft). Pencere ancak **dışarıya bakan bir duvarı olan** mahale konur.
Her mahal için dört kenarın ötesinde ne olduğuna bak (komşu mahal mi, dışarısı mı). Sonucu üçe
ayır ve **beyan et**:
- **cephesi var** → pencere alır,
- **balkona/ışıklığa açılıyor** → pencere değil, balkon kapısı tipi blok,
- **iç mahal** → pencere ALMAZ.
Bu ayrımı yaptıktan sonra **SORMADAN devam et**: mümkün olanları yap, alamayanları nedeniyle
listele. Kullanıcı "her mahale" dediyse bile, imkânsız olanı sormak yerine yapılabilirini yapıp
farkı raporlamak doğru davranıştır.
Pencere **dış duvara** konur (mahalin dışarıya bakan yüzü). Her mahal için:
- Mahalin `find_spaces` bbox'ından dışa bakan kenarı bul (o kenarın ötesinde başka mahal yoksa
dış duvardır).
- O kenardaki duvarın **iki yüz çizgisini** ve kalınlığını oku (`cad.query` + `cad.entities`).
- Boşluğun konumu: kullanıcı söylediyse onu uygula ("her odaya bir tane", "salona iki tane").
Söylemediyse **duvarın ortasına** yerleştir ve bunu beyan et — kullanıcı "her mahale bir
pencere" gibi bir kural vermediyse kendi kararını beyanla ver.
- Boşluk duvarın ucundan en az bir duvar kalınlığı kadar içeride kalsın; köşeye dayanmış
pencere yanlıştır.
### 4. Duvarı KIR — `edit_geometry` ile, silerek DEĞİL
Boşluk açmak bir "break" işlemidir ve tek başına bir primitifi yoktur, ama artık `edit_geometry`
var: **`trim` handle'ı, xdata'yı ve katmanı KORUR.** Silip yeniden çizmek son çare; sildiğin
çizginin kimliği kaybolur.
Sıra önemli — kenar çizgileri trim'in SINIRI olur:
1. `get_objects_in_region` ile boşluğun düşeceği yerdeki **iki yüz çizgisinin handle'larını**
al (dar bir bölge ver; başka çizgi toplama). Uç koordinatlarını da oku, parçaları onlardan
üreteceksin.
2. `draw` ile **iki kenar (jamb) çizgisini** çiz: boşluğun uçlarında, dış yüzden iç yüze,
duvarla aynı katmanda.
3. `edit_geometry op:"trim"` — her yüz çizgisini, `boundary_handles` olarak o kenar çizgilerini
vererek kırp. `keep_point` **KORUNACAK** tarafı gösterir (atılacak tarafı değil): boşluğun
solunda kalan parçayı tutmak için solda bir nokta ver.
4. Trim tek parça bırakır — boşluğun ÖTE yanındaki parçayı `draw` ile çiz.
Yani orijinal çizgi bir parça olarak yaşamaya devam eder, yalnız kalan parça yeni doğar.
`delete_entities` + iki yeni çizgi de aynı görüntüyü verir ama iki handle birden kaybolur;
mecbur kalmadıkça yapma.
Bir yüz çizgisi birden çok pencere taşıyorsa: bir kez trim'le (ilk parça), kalan N parçayı tek
`run_script` içinde `cad.draw` ile çiz (N pencere → N+1 parça).
Nesneyi taşımak/döndürmek gerekirse `modify_entities`'in `transform` alanı bunu da handle
koruyarak yapar (`move`/`rotate`/`scale`/`mirror`, açı RADYAN) — bunun için de sil-yeniden-çiz
yapma.
### 5. Bloğu yerleştir — ÖNCE TEK TANE
**`rotation` RADYAN'dır, derece değil.** 90° = `Math.PI/2`, 180° = `Math.PI`. Derece yazmak
HATA DÖNDÜRMEZ, blok sessizce yanlış açıya oturur. Negatif `scale` bloğu AYNALAR — asimetrik bir
pencerede (denizlik, kanat yönü) hangi yüzün dışa baktığını bu belirler.
**Dinamik blokta varyantı yerleştirirken ver.** `insert_blocks`'un `dynamic_properties` alanına
istediğin parametre değerlerini koy; vermezsen blok **VARSAYILAN** varyantıyla doğar ve 20
pencereyi kullanıcı elle düzeltir. Ad ve değerleri `dynamic_property_choices`'tan al, uydurma —
bilinmeyen ad ya da listede olmayan değer o yerleşimi hata ile reddeder. Zaten yerleştirilmiş
blokların varyantını sonradan değiştirmek için `set_block_properties` kullan.
**Etiketsiz 0/1 parametreler (Flip, Hinge, Swing) aynalama parametresidir** ve hangi sayının
hangi yöne denk geldiği BLOĞA GÖRE DEĞİŞİR — API'ye yalnız 0 ve 1 ulaşır. Tahmin etme; aşağıdaki
tek-pencere denemesinde bunu da doğrula.
Dönme + aynalama kombinasyonu kafadan doğru hesaplanmaz: blok ya ters yöne uzar, ya çıkıntısı
içeri bakar. Bu yüzden:
1. **Bir tane** yerleştir (`insert_blocks`).
2. O pencerenin bbox'ını (biraz pay ekleyerek) `render_and_verify` ile render et ve BAK:
- Blok boşluğu TAM dolduruyor mu? (taşıyor ya da eksik kalıyorsa yanlış uç/ölçek)
- Çıkıntılı parça (denizlik/balkon) DIŞARI mı bakıyor?
- Kenar çizgileri görünüyor mu?
3. Yanlışsa dönmeyi/ölçeği düzelt ve tekrar bak. Doğru kombinasyonu bulunca **kalanları batch
yerleştir** — her cephe için dönme farklıdır, aynı cephedekiler aynıdır.
### 6. Denetle ve onaya sun
Her pencere için `render_and_verify` ile o bölgeye bak (toplu görüntüde bu ölçekteki hata
görünmez). Aradığın kusurlar:
- Boşluk açılmamış, blok kesintisiz duvarın üstünde duruyor.
- Kenar çizgisi eksik → duvar açık ağızlı.
- Boşluk blok genişliğinden farklı → blok taşıyor ya da boşluk kalıyor.
- Blok ters yönde/aynalanmış.
- Duvar parçası fazla ya da eksik silinmiş (komşu duvar da gitmiş).
Sonra `create_preview` → kullanıcı onayı → `commit_changes`.
## Cevabında beyan et
| pencere | mahal | blok | kasa | boşluk | duvar | dönme |
|---|---|---|---|---|---|---|
| 1 | ⟨mahal adı⟩ | ⟨blok adı⟩ | ⟨bbox⟩ | ⟨açıklık⟩ | ⟨cephe⟩ | ⟨açı⟩ |
Ayrıca:
- Bloğu nereden aldığın (çizimde tanımlıydı / klonladın / kullanıcı verdi / anonim adlıydı,
kullanımından tanıdın).
- Her blok için ölçtüğün kasa genişliği ve türettiğin boşluk (ikisi ayrı sayı).
- **Çözülmüş bir kopyadan kopyaladıysan bunu açıkça söyle** ve kapanış sayısını ver
(`ham − silinen + eklenen = hedef`).
- Pencere sayısına nasıl karar verdiğin (kullanıcı söyledi mi, sen mi seçtin).
- Pencere ALMAYAN mahaller ve nedeni (iç mahal / cephesi yok / çok dar).
## Bilinen sınır
Bir çizgiyi ortadan İKİYE bölen tek bir "break" işlemi yok: `edit_geometry op:"trim"` yalnız
`keep_point`'in gösterdiği parçayı bırakır, öteki parça `draw` ile yeniden doğar. Yani boşluğun
bir yanı orijinal handle'ı korur, öteki yanı yeni bir handle alır — aynı çizgiye başka bir
adımda handle ile atıfta bulunuyorsan önce kırmayı bitir.
`edit_geometry` v1 yalnız Line ve açık/yaysız Polyline düzenler; yay, daire, spline ve
kapalı/bulge'lu polyline `skipped` içinde gerekçesiyle beyan edilir. Duvarı bunlardan biriyle
çizilmiş bir planda kırma elle (sil + çiz) yapılır.
## Example prompts
- /pencere-yerlesimi İşaretlediğim bölgedeki her mahale bir pencere çiz.
- /pencere-yerlesimi Bu dairenin güney cephesine pencere koy.
- /pencere-yerlesimi Odalara, çizimde zaten tanımlı olan pencere bloğunu kullanarak pencere ekle.
- /pencere-yerlesimi Salon ile balkon arasına balkon kapısı yerleştir.