2010-03-21 6 views
5

Ten temat został porysowany raz lub dwa razy, ale nadal jestem zdziwiony. Google też nie był przyjazny.Jak skonfigurować układ współrzędnych Quartz2D użytkownika ze skalowaniem unikającym rysowania rozmytego?

Ponieważ mechanizm kwarcowy zezwala na dowolne układy współrzędnych wykorzystujące transformacje afiniczne, chcę móc rysować takie rzeczy, jak plany pięter z rzeczywistą współrzędną, np. stopy.

Tak więc, na zasadzie przykładu, chcę przeskalować widok, aby podczas rysowania prostokąta o wymiarach 10x10 (na przykład o 10-calowym polu) otrzymywałam prostokąt o wymiarach 60 x 60 pikseli.

Działa, z wyjątkiem prostokąta, który otrzymuję, jest dość rozmyta. Kolejne pytanie tutaj dostałem odpowiedź, która wyjaśnia dlaczego. Jednak nie jestem pewien, czy rozumiem ten powód, a co więcej, nie wiem, jak to naprawić. Tu jest mój kodu:

mogę ustawić układ współrzędnych w moim awakeFromNib niestandardowego sposobu widzenia:

- (void) awakeFromNib { 
    CGAffineTransform scale = CGAffineTransformMakeScale(6.0, 6.0); 
    self.transform = scale; 
} 

I tu jest moje losowanie rutyna:

- (void)drawRect:(CGRect)rect { 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGRect r = CGRectMake(10., 10., 10., 10.); 
    CGFloat lineWidth = 1.0; 
    CGContextStrokeRectWithWidth(context, r, lineWidth); 
} 

Plac uzyskać skalowany jest w porządku , ale całkowicie niewyraźne. Zabawa z lineWidth nie pomaga: gdy ustawienie lineWidth jest mniejsze, staje się jaśniejsze, ale nie ostrzejsze.

Czy istnieje sposób skonfigurowania widoku na skalowany układ współrzędnych, aby można było używać współrzędnych domeny? A może powinienem wrócić i wdrożyć skalowanie w moich procedurach rysowania?

Należy zauważyć, że ten problem nie występuje podczas tłumaczenia lub obrotu.

Dzięki

Odpowiedz

2

Cóż, tak często, wyjaśnianie problemu prowadzi mnie do rozwiązania.

Problem polega na tym, że właściwość transformacji widoku jest stosowana do niej po pobraniu do bufora bitów. Transformację skalującą należy zastosować przed rysowaniem, tzn. w metodzie drawRect. Tak zarysowuje awakeFromNib dałem, a tutaj jest poprawna drawRect:

- (void)drawRect:(CGRect)rect { 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGAffineTransform scale = CGAffineTransformMakeScale(6.0, 6.0); 
    CGContextConcatCTM(context, scale); 
    CGRect r = CGRectMake(10., 10., 10., 10.); 
    CGFloat lineWidth = 0.1; 
    CGContextStrokeRectWithWidth(context, r, lineWidth); 
} 
+1

Jeśli chcesz ustawić szerokość linii w punktach niezależnie od współczynnika skali, ustaw go na "pożądaną liczbę punktów/współczynnik skali". Przykłady: Wartość domyślna to 1 pt/1 × = 1; linia 1-punktowa w twoim współczynniku 6 × wynosi '1.0/6.0'; linia 2-punktowa to "2.0/6.0". –

10

przycisk [pogłaskał] prostokąt uzyskać jest dość niewyraźny.

Zazwyczaj, to dlatego, że wykreślono prostokąt na całe numerycznych współrzędnych a szerokość linii wynosi 1.

W PostScript (a więc w jego potomków: zestaw klas AppKit, PDF i kwarc), rysunek jednostek domyślnie do punktów, 1 punkt to dokładnie 1/72 cala. Obecnie Mac i iPhone * traktują każdy taki punkt jako 1 piksel, niezależnie od rzeczywistej rozdzielczości ekranu (ów), więc w sensie praktycznym punkty (domyślnie na komputerach Mac i iPhone) są równe pikselom.

W języku PostScript i jego elementach potomnych współrzędne całkowite biegną między punktami. 0, 0, na przykład, to lewy dolny róg dolnego lewego punktu. 1, 0 to prawy dolny róg tego samego punktu (i lewy dolny róg następnego punktu po prawej).

Skok jest wyśrodkowany na ścieżce, którą głaskasz. Tak więc połowa znajdzie się na ścieżce, na wpół na zewnątrz.

W (koncepcyjnie) świecie komputerów Mac z 72-punktową rozdzielczością te dwa fakty łączą się, tworząc problem. Jeśli 1 punkt jest równy 1 piksel, a jedno uderzenie jest stosowane między dwoma pikselami, połowa uderzenia uderzy w każdy z tych pikseli.

kwarcowy co najmniej uczyni to poprzez malowanie bieżącego koloru do obu pikseli w jednej połowie alpha z kolorów. Określa to, o ile piksel jest objęty pojęciowym obrysem; jeśli użyto szerokości linii o szerokości 1,5, połowa z nich to 0,75 pt, co stanowi trzy czwarte każdego piksela o wartości 1 pt, więc kolor będzie renderowany na poziomie 0,75 alfa. To oczywiście prowadzi do naturalnego wniosku: jeśli używasz 2-punktowej szerokości linii, każdy piksel jest całkowicie zakryty, więc alfa będzie 1. Dlatego możesz zobaczyć ten efekt z jednym uderzeniem, a nie Skok 2-punktowy.

Istnieje kilka obejścia:

  • Half-punkt tłumaczenie: Dokładnie to, co jest napisane na pudełku, tłumaczyć się i prawo o pół punktu, kompensując wspomniany 1-PT-cut-in -przeciętny podział.

    Działa to w prostych przypadkach, ale płatki, kiedy ty obejmować żadnych innych przekształceń koordynować oprócz tłumaczeń cały punkt. Oznacza to, że możesz tłumaczyć o 30, 20 i nadal będzie działać, ale jeśli przetłumaczysz o 33 + 1/3, 25.252525 ... lub jeśli w ogóle zmienisz lub obrócisz, twoje półpunktowe tłumaczenie będzie bezużyteczne .

  • udar wewnętrzna: Klip, potem dwukrotnie szerokość linii (bo jesteś tylko będzie zwrócić połowę), a następnie skok.

    To może wymagać gstate żonglerka, jeśli masz dużo inny rysunek zrobić, ponieważ nie chce, że ścieżką wpływające na inny rysunek.

  • zewnętrznego skoku: w zasadzie taka sama jak wewnętrzna udaru, z wyjątkiem tego odwrócić ścieżkę przed wycinek.

    Może być lepsza (mniej gstate żonglerka) niż wewnętrzna udaru, jeśli jesteś pewien, że chcesz ścieżki do udaru nie będzie się pokrywać. Z drugiej strony, jeśli chcesz również wypełnić ścieżkę, żonglerka gstate powraca.

* To nie będzie trwać wiecznie. Apple od jakiegoś czasu zrzuca wskazówki, że w pewnym momencie zamierzają zmienić rozdzielczość rysowania Maca. Fundament API dla takiej zmiany jest już prawie obecny; to wszystko zależy od Apple'a, który rzuca przełącznik.

+0

wszystko jest bardzo prawdziwe, chyba że nie jest to przyczyną niewyraźności, której doświadczyłem. Nieostrość jest spowodowana faktem, że "UIView.transform" jest stosowany do widoku jako krok po usunięciu bledu. W tym przypadku skaluje się mapę bitową narysowaną przez 'drawRect'. Po prostu przez zastosowanie transformacji * na początku * 'drawRect' naprawia to. Dzięki temu 'UIView.transform' staje się bezużyteczny do skalowania. Oczywiście, nadal widzę to, co opisujesz - piksel na obwodzie. Wizualne wrażenie na pionowych i poziomych obrysach o wielkości 1 piksela ma wyglądać raczej na szaro niż na czarno, niż na nieostrość. –

Powiązane problemy