1/* PathContour.m 2 * Object to build contour of paths and images using a raster algorithm (scan) 3 * 4 * Copyright (C) 2000-2011 by vhf interservice GmbH 5 * Author: Ilonka Fleischmann 6 * 7 * created: 2000-02-23 8 * modified: 2011-04-06 (-contourImage:with: whiteStop for jpg - white tolerances) 9 * 2010-03-03 (-contourPath:with: setDirectionCCW:) 10 * 2008-04-18 (optimizePath close now) 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the vhf Public License as 14 * published by vhf interservice GmbH. Among other things, the 15 * License requires that the copyright notices and this notice 16 * be preserved on all copies. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 * See the vhf Public License for more details. 22 * 23 * You should have received a copy of the vhf Public License along 24 * with this program; see the file LICENSE. If not, write to vhf. 25 * 26 * vhf interservice GmbH, Im Marxle 3, 72119 Altingen, Germany 27 * eMail: info@vhf.de 28 * http://www.vhf.de 29 */ 30 31#include <AppKit/AppKit.h> 32#include <VHFShared/types.h> 33#include <VHFShared/vhfCommonFunctions.h> 34#include "../DocView.h" // ??? 35#include "VGraphic.h" 36#include "PathContour.h" 37 38#define DEBUG_CONTUR 0 39 40/* Private methods 41*/ 42@interface PathContour(PrivateMethods) 43 44 45@end 46 47@implementation PathContour 48 49//static NSBitmapImageRep *bitmapImageRep; 50static int size, bytesPerRow; 51static unsigned char *data, black=0, white=255, whiteStop=240; 52static int 53Arc2cnt = 5, 54Arc2y[5] = {-2, -1, 0, 1, 2}, Arc2x[5] = {-2, -2, -2, -2, -2}, 55Arc2rowcnt[5] = {5, 5, 5, 5, 5}, 56Arc3cnt = 7, 57Arc3y[7] = {-3, -2, -1, 0, 1, 2, 3}, 58Arc3x[7] = {-3, -3, -3, -3, -3, -3, -3}, 59Arc3rowcnt[7] = {7, 7, 7, 7, 7, 7, 7}, 60Arc4cnt = 9, 61Arc4y[9] = {-4, -3, -2, -1, 0, 1, 2, 3, 4}, 62Arc4x[9] = {-3, -4, -4, -4, -4, -4, -4, -4, -3}, 63Arc4rowcnt[9] = {7, 9, 9, 9, 9, 9, 9, 9, 7}; 64 65static int 66Arc5cnt = 11, 67Arc5y[11] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, 68Arc5x[11] = {-3, -4, -5, -5, -5, -5, -5, -5, -5, -4, -3}, 69Arc5rowcnt[11] = {7,9,11,11,11,11,11,11,11,9,7}, 70Arc6cnt = 13, 71Arc6y[13] = {-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6}, 72Arc6x[13] = {-3,-5,-5,-6,-6,-6,-6,-6,-6,-6,-5,-5,-3}, 73Arc6rowcnt[13] = {7,11,11,13,13,13,13,13,13,13,11,11,7}, 74Arc7cnt = 15, 75Arc7y[15] = {-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7}, 76Arc7x[15] = {-3,-5,-6,-6,-7,-7,-7,-7,-7,-7,-7,-6,-6,-5,-3}, 77Arc7rowcnt[15] = {7,11,13,13,15,15,15,15,15,15,15,13,13,11,7}, 78Arc8cnt = 17, 79Arc8y[17] = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8}, 80Arc8x[17] = {-3,-5,-6,-7,-7,-8,-8,-8,-8,-8,-8,-8,-7,-7,-6,-5,-3}, 81Arc8rowcnt[17] = {7,11,13,15,15,17,17,17,17,17,17,17,15,15,13,11,7}, 82Arc9cnt = 19, 83Arc9y[19] = {-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9}, 84Arc9x[19] = {-4,-6,-7,-8,-8,-9,-9,-9,-9,-9,-9,-9,-9,-9,-8,-8,-7,-6,-4}, 85Arc9rowcnt[19] = {9,13,15,17,17,19,19,19,19,19,19,19,19,19,17,17,15,13,9}, 86Arc10cnt = 21, 87Arc10y[21] = {-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10}, 88Arc10x[21] = {-5,-6,-8,-8,-9,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-9,-8,-8,-6,-5}, 89Arc10rowcnt[21] = {11,13,17,17,19,21,21,21,21,21,21,21,21,21,21,21,19,17,17,13,11}, 90Arc11cnt = 23, 91Arc11y[23] = {-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11}, 92Arc11x[23] = {-5,-6,-8,-9,-9,-10,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-10,-9,-9,-8,-6,-5}, 93Arc11rowcnt[23] = {11,13,17,19,19,21,23,23,23,23,23,23,23,23,23,23,23,21,19,19,17,13,11}, 94Arc12cnt = 25, 95Arc12y[25] = {-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12}, 96Arc12x[25] = {-5,-7,-8,-9,-10,-11,-11,-12,-12,-12,-12,-12,-12,-12,-12,-12,-12,-12,-11,-11,-10,-9,-8,-7,-5}, 97Arc12rowcnt[25] = {11,15,17,19,21,23,23,25,25,25,25,25,25,25,25,25,25,25,23,23,21,19,17,15,11}, 98Arc13cnt = 27, 99Arc13y[27] = {-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13}, 100Arc13x[27] = {-5,-7,-9,-10,-11,-11,-12,-12,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-12,-12,-11,-11,-10,-9,-7,-5}, 101Arc13rowcnt[27] = {11,15,19,21,23,23,25,25,27,27,27,27,27,27,27,27,27,27,27,25,25,23,23,21,19,15,11}, 102Arc14cnt = 29, 103Arc14y[29] = {-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14}, 104Arc14x[29] = {-5,-7,-9,-10,-11,-12,-12,-13,-13,-14,-14,-14,-14,-14,-14,-14,-14,-14,-14,-14,-13,-13,-12,-12,-11,-10,-9,-7,-5}, 105Arc14rowcnt[29] = {11,15,19,21,23,25,25,27,27,29,29,29,29,29,29,29,29,29,29,29,27,27,25,25,23,21,19,15,11}, 106Arc15cnt = 31, 107Arc15y[31] = {-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, 108Arc15x[31] = {-5,-8,-9,-11,-12,-12,-13,-14,-14,-14,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-14,-14,-14,-13,-12,-12,-11,-9,-8,-5}, 109Arc15rowcnt[31] = {10,16,18,22,24,24,26,28,28,28,30,30,30,30,30,30,30,30,30,30,30,28,28,28,26,24,24,22,18,16,10}, 110Arc16cnt = 33, 111Arc16y[33] = {-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}, 112Arc16x[33] = {-5,-8,-9,-11,-12,-13,-13,-14,-15,-15,-15,-16,-16,-16,-16,-16,-16,-16,-16,-16,-16,-16,-15,-15,-15,-14,-13,-13,-12,-11,-9,-8,-5}, 113Arc16rowcnt[33] = {10,16,18,22,24,26,26,28,30,30,30,32,32,32,32,32,32,32,32,32,32,32,30,30,30,28,26,26,24,22,18,16,10}, 114Arc17cnt = 35, 115Arc17y[35] = {-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}, 116Arc17x[35] = {-5,-8,-10,-11,-13,-13,-14,-15,-15,-16,-16,-16,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-16,-16,-16,-15,-15,-14,-13,-13,-11,-10,-8,-5}, 117Arc17rowcnt[35] = {10,16,20,22,26,26,28,30,30,32,32,32,34,34,34,34,34,34,34,34,34,34,34,32,32,32,30,30,28,26,26,22,20,16,10}, 118Arc18cnt = 37, 119Arc18y[37] = {-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}, 120Arc18x[37] = {-5,-8,-10,-11,-13,-14,-14,-15,-16,-16,-17,-17,-17,-18,-18,-18,-18,-18,-18,-18,-18,-18,-18,-18,-17,-17,-17,-16,-16,-15,-14,-14,-13,-11,-10,-8,-5}, 121Arc18rowcnt[37] = {10,16,20,22,26,28,28,30,32,32,34,34,34,36,36,36,36,36,36,36,36,36,36,36,34,34,34,32,32,30,28,28,26,22,20,16,10}, 122Arc19cnt = 39, 123Arc19y[39] = {-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}, 124Arc19x[39] = {-5,-9,-10,-12,-13,-14,-15,-16,-16,-17,-18,-18,-18,-18,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-18,-18,-18,-18,-17,-16,-16,-15,-14,-13,-12,-10,-9,-5}, 125Arc19rowcnt[39] = {10,18,20,24,26,28,30,32,32,34,36,36,36,36,38,38,38,38,38,38,38,38,38,38,38,36,36,36,36,34,32,32,30,28,26,24,20,18,10}, 126Arc20cnt = 41, 127Arc20y[41] = {-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}, 128Arc20x[41] = {-5,-9,-10,-12,-13,-15,-15,-16,-17,-17,-18,-19,-19,-19,-19,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-19,-19,-19,-19,-18,-17,-17,-16,-15,-15,-13,-12,-10,-9,-5}, 129Arc20rowcnt[41] = {10,18,20,24,26,30,30,32,34,34,36,38,38,38,38,40,40,40,40,40,40,40,40,40,40,40,38,38,38,38,36,34,34,32,30,30,26,24,20,18,10}, 130Arc21cnt = 43, 131Arc21y[43] = {-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21}, 132Arc21x[43] = {-5,-9,-11,-12,-14,-15,-16,-17,-17,-18,-19,-19,-20,-20,-20,-20,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-20,-20,-20,-20,-19,-19,-18,-17,-17,-16,-15,-14,-12,-11,-9,-5}, 133Arc21rowcnt[43] = {10,18,22,24,28,30,32,34,34,36,38,38,40,40,40,40,42,42,42,42,42,42,42,42,42,42,42,40,40,40,40,38,38,36,34,34,32,30,28,24,22,18,10}, 134Arc22cnt = 45, 135Arc22y[45] = {-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22}, 136Arc22x[45] = {-5,-9,-11,-12,-14,-15,-16,-17,-18,-18,-19,-20,-20,-21,-21,-21,-21,-22,-22,-22,-22,-22,-22,-22,-22,-22,-22,-22,-21,-21,-21,-21,-20,-20,-19,-18,-18,-17,-16,-15,-14,-12,-11,-9,-5}, 137Arc22rowcnt[45] = {10,18,22,24,28,30,32,34,36,36,38,40,40,42,42,42,42,44,44,44,44,44,44,44,44,44,44,44,42,42,42,42,40,40,38,36,36,34,32,30,28,24,22,18,10}, 138Arc23cnt = 47, 139Arc23y[47] = {-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}, 140Arc23x[47] = {-5,-10,-11,-13,-14,-16,-17,-18,-18,-19,-20,-20,-21,-22,-22,-22,-22,-22,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-22,-22,-22,-22,-22,-21,-20,-20,-19,-18,-18,-17,-16,-14,-13,-11,-10,-5}, 141Arc23rowcnt[47] = {10,20,22,26,28,32,34,36,36,38,40,40,42,44,44,44,44,44,46,46,46,46,46,46,46,46,46,46,46,44,44,44,44,44,42,40,40,38,36,36,34,32,28,26,22,20,10}, 142Arc24cnt = 49, 143Arc24y[49] = {-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}, 144Arc24x[49] = {-5,-10,-11,-13,-14,-16,-17,-18,-19,-19,-20,-21,-21,-22,-23,-23,-23,-23,-23,-24,-24,-24,-24,-24,-24,-24,-24,-24,-24,-24,-23,-23,-23,-23,-23,-22,-21,-21,-20,-19,-19,-18,-17,-16,-14,-13,-11,-10,-5}, 145Arc24rowcnt[49] = {10,20,22,26,28,32,34,36,38,38,40,42,42,44,46,46,46,46,46,48,48,48,48,48,48,48,48,48,48,48,46,46,46,46,46,44,42,42,40,38,38,36,34,32,28,26,22,20,10}, 146Arc25cnt = 51, 147Arc25y[51] = {-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25}, 148Arc25x[51] = {-5,-10,-12,-13,-15,-16,-18,-19,-19,-20,-21,-21,-22,-23,-23,-24,-24,-24,-24,-24,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-24,-24,-24,-24,-24,-23,-23,-22,-21,-21,-20,-19,-19,-18,-16,-15,-13,-12,-10,-5}, 149Arc25rowcnt[51] = {10,20,24,26,30,32,36,38,38,40,42,42,44,46,46,48,48,48,48,48,50,50,50,50,50,50,50,50,50,50,50,48,48,48,48,48,46,46,44,42,42,40,38,38,36,32,30,26,24,20,10}, 150Arc26cnt = 53, 151Arc26y[53] = {-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26}, 152Arc26x[53] = {-5,-10,-12,-14,-15,-16,-18,-19,-20,-20,-21,-22,-23,-23,-24,-24,-25,-25,-25,-25,-25,-26,-26,-26,-26,-26,-26,-26,-26,-26,-26,-26,-25,-25,-25,-25,-25,-24,-24,-23,-23,-22,-21,-20,-20,-19,-18,-16,-15,-14,-12,-10,-5}, 153Arc26rowcnt[53] = {10,20,24,28,30,32,36,38,40,40,42,44,46,46,48,48,50,50,50,50,50,52,52,52,52,52,52,52,52,52,52,52,50,50,50,50,50,48,48,46,46,44,42,40,40,38,36,32,30,28,24,20,10}, 154Arc27cnt = 55, 155Arc27y[55] = {-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27}, 156Arc27x[55] = {-5,-10,-12,-14,-15,-17,-18,-20,-20,-21,-22,-22,-23,-24,-24,-25,-25,-26,-26,-26,-26,-26,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-26,-26,-26,-26,-26,-25,-25,-24,-24,-23,-22,-22,-21,-20,-20,-18,-17,-15,-14,-12,-10,-5}, 157Arc27rowcnt[55] = {10,20,24,28,30,34,36,40,40,42,44,44,46,48,48,50,50,52,52,52,52,52,54,54,54,54,54,54,54,54,54,54,54,52,52,52,52,52,50,50,48,48,46,44,44,42,40,40,36,34,30,28,24,20,10}, 158Arc28cnt = 57, 159Arc28y[57] = {-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28}, 160Arc28x[57] = {-5,-10,-13,-14,-16,-17,-19,-20,-21,-22,-22,-23,-24,-24,-25,-26,-26,-26,-27,-27,-27,-27,-27,-28,-28,-28,-28,-28,-28,-28,-28,-28,-28,-28,-27,-27,-27,-27,-27,-26,-26,-26,-25,-24,-24,-23,-22,-22,-21,-20,-19,-17,-16,-14,-13,-10,-5}, 161Arc28rowcnt[57] = {10,20,26,28,32,34,38,40,42,44,44,46,48,48,50,52,52,52,54,54,54,54,54,56,56,56,56,56,56,56,56,56,56,56,54,54,54,54,54,52,52,52,50,48,48,46,44,44,42,40,38,34,32,28,26,20,10}, 162Arc29cnt = 59, 163Arc29y[59] = {-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29}, 164Arc29x[59] = {-5,-10,-13,-14,-16,-17,-19,-20,-21,-22,-23,-23,-24,-25,-25,-26,-27,-27,-27,-28,-28,-28,-28,-28,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-28,-28,-28,-28,-28,-27,-27,-27,-26,-25,-25,-24,-23,-23,-22,-21,-20,-19,-17,-16,-14,-13,-10,-5}, 165Arc29rowcnt[59] = {10,20,26,28,32,34,38,40,42,44,46,46,48,50,50,52,54,54,54,56,56,56,56,56,58,58,58,58,58,58,58,58,58,58,58,56,56,56,56,56,54,54,54,52,50,50,48,46,46,44,42,40,38,34,32,28,26,20,10}, 166Arc30cnt = 61, 167Arc30y[61] = {-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}, 168Arc30x[61] = {-5,-10,-13,-15,-16,-18,-19,-21,-22,-23,-23,-24,-25,-25,-26,-27,-27,-28,-28,-28,-29,-29,-29,-29,-29,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-29,-29,-29,-29,-29,-28,-28,-28,-27,-27,-26,-25,-25,-24,-23,-23,-22,-21,-19,-18,-16,-15,-13,-10,-5}, 169Arc30rowcnt[61] = {10,20,26,30,32,36,38,42,44,46,46,48,50,50,52,54,54,56,56,56,58,58,58,58,58,60,60,60,60,60,60,60,60,60,60,60,58,58,58,58,58,56,56,56,54,54,52,50,50,48,46,46,44,42,38,36,32,30,26,20,10}, 170Arc31cnt = 63, 171Arc31y[63] = {-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}, 172Arc31x[63] = {-5,-10,-13,-15,-16,-18,-19,-21,-22,-23,-24,-24,-25,-26,-26,-27,-28,-28,-29,-29,-29,-30,-30,-30,-30,-30,-31,-31,-31,-31,-31,-31,-31,-31,-31,-31,-31,-30,-30,-30,-30,-30,-29,-29,-29,-28,-28,-27,-26,-26,-25,-24,-24,-23,-22,-21,-19,-18,-16,-15,-13,-10,-5}, 173Arc31rowcnt[63] = {10,20,26,30,32,36,38,42,44,46,48,48,50,52,52,54,56,56,58,58,58,60,60,60,60,60,62,62,62,62,62,62,62,62,62,62,62,60,60,60,60,60,58,58,58,56,56,54,52,52,50,48,48,46,44,42,38,36,32,30,26,20,10}, 174Arc32cnt = 65, 175Arc32y[65] = {-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}, 176Arc32x[65] = {-5,-10,-14,-15,-17,-18,-20,-21,-23,-24,-24,-25,-26,-26,-27,-28,-28,-29,-30,-30,-30,-30,-31,-31,-31,-31,-31,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-31,-31,-31,-31,-31,-30,-30,-30,-30,-29,-28,-28,-27,-26,-26,-25,-24,-24,-23,-21,-20,-18,-17,-15,-14,-10,-5}, 177Arc32rowcnt[65] = {10,20,28,30,34,36,40,42,46,48,48,50,52,52,54,56,56,58,60,60,60,60,62,62,62,62,62,64,64,64,64,64,64,64,64,64,64,64,62,62,62,62,62,60,60,60,60,58,56,56,54,52,52,50,48,48,46,42,40,36,34,30,28,20,10}, 178Arc33cnt = 67, 179Arc33y[67] = {-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33}, 180Arc33x[67] = {-5,-10,-14,-15,-17,-18,-20,-21,-23,-24,-25,-25,-26,-27,-27,-28,-29,-29,-30,-31,-31,-31,-31,-32,-32,-32,-32,-32,-33,-33,-33,-33,-33,-33,-33,-33,-33,-33,-33,-32,-32,-32,-32,-32,-31,-31,-31,-31,-30,-29,-29,-28,-27,-27,-26,-25,-25,-24,-23,-21,-20,-18,-17,-15,-14,-10,-5}, 181Arc33rowcnt[67] = {10,20,28,30,34,36,40,42,46,48,50,50,52,54,54,56,58,58,60,62,62,62,62,64,64,64,64,64,66,66,66,66,66,66,66,66,66,66,66,64,64,64,64,64,62,62,62,62,60,58,58,56,54,54,52,50,50,48,46,42,40,36,34,30,28,20,10}, 182Arc34cnt = 69, 183Arc34y[69] = {-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34}, 184Arc34x[69] = {-5,-10,-14,-16,-18,-20,-21,-22,-23,-25,-25,-26,-27,-28,-29,-29,-30,-30,-31,-31,-32,-32,-32,-32,-33,-33,-33,-33,-33,-34,-34,-34,-34,-34,-34,-34,-34,-34,-34,-34,-33,-33,-33,-33,-33,-32,-32,-32,-32,-31,-31,-30,-30,-29,-29,-28,-27,-26,-25,-25,-23,-22,-21,-20,-18,-16,-14,-10,-5}, 185Arc34rowcnt[69] = {10,20,28,32,36,40,42,44,46,50,50,52,54,56,58,58,60,60,62,62,64,64,64,64,66,66,66,66,66,68,68,68,68,68,68,68,68,68,68,68,66,66,66,66,66,64,64,64,64,62,62,60,60,58,58,56,54,52,50,50,46,44,42,40,36,32,28,20,10}, 186Arc35cnt = 71, 187Arc35y[71] = {-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35}, 188Arc35x[71] = {-5,-10,-15,-16,-18,-20,-21,-23,-24,-25,-26,-27,-28,-28,-29,-30,-30,-31,-31,-32,-33,-33,-33,-33,-33,-34,-34,-34,-34,-34,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-34,-34,-34,-34,-34,-33,-33,-33,-33,-33,-32,-31,-31,-30,-30,-29,-28,-28,-27,-26,-25,-24,-23,-21,-20,-18,-16,-15,-10,-5}, 189Arc35rowcnt[71] = {10,20,30,32,34,40,42,46,48,50,52,54,56,56,58,60,60,62,62,64,66,66,66,66,66,68,68,68,68,68,70,70,70,70,70,70,70,70,70,70,70,68,68,68,68,68,66,66,66,66,66,64,62,62,60,60,58,56,56,54,52,50,48,46,42,40,34,32,30,20,10}, 190Arc36cnt = 73, 191Arc36y[73] = {-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36}, 192Arc36x[73] = {-9,-12,-15,-17,-18,-20,-22,-23,-24,-25,-26,-27,-28,-29,-30,-30,-31,-31,-32,-33,-33,-34,-34,-34,-35,-35,-35,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-35,-35,-35,-34,-34,-34,-33,-33,-32,-31,-31,-30,-30,-29,-28,-27,-26,-25,-24,-23,-22,-20,-18,-17,-15,-12,-9}, 193Arc36rowcnt[73] = {18,24,30,34,38,40,44,46,48,50,52,54,56,58,60,60,62,62,64,66,66,68,68,68,70,70,70,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,70,70,70,68,68,68,66,66,64,62,62,60,60,58,56,54,52,50,48,46,44,40,38,34,30,24,18}, 194Arc37cnt = 75, 195Arc37y[75] = {-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37}, 196Arc37x[75] = {-9,-12,-15,-17,-19,-21,-22,-23,-24,-26,-27,-28,-28,-29,-30,-31,-32,-32,-33,-33,-34,-34,-35,-35,-35,-36,-36,-36,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-36,-36,-36,-35,-35,-35,-34,-34,-33,-33,-32,-32,-31,-30,-29,-28,-28,-27,-26,-24,-23,-22,-21,-19,-17,-15,-12,-9}, 197Arc37rowcnt[75] = {18,24,30,34,38,42,44,46,48,52,54,56,56,58,60,62,64,64,66,66,68,68,70,70,70,72,72,72,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,72,72,72,70,70,70,68,68,66,66,64,64,62,60,58,56,56,54,52,48,46,44,42,38,34,30,24,18}, 198Arc38cnt = 77, 199Arc38y[77] = {-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38}, 200Arc38x[77] = {-9,-12,-15,-17,-19,-21,-22,-24,-25,-26,-27,-28,-29,-30,-31,-31,-32,-33,-33,-34,-34,-35,-35,-36,-36,-36,-37,-37,-37,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-37,-37,-37,-36,-36,-36,-35,-35,-34,-34,-33,-33,-32,-31,-31,-30,-29,-28,-27,-26,-25,-24,-22,-21,-19,-17,-15,-12,-9}, 201Arc38rowcnt[77] = {18,24,30,34,38,42,44,48,50,52,54,56,58,60,62,62,64,66,66,68,68,70,70,72,72,72,74,74,74,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,74,74,74,72,72,72,70,70,68,68,66,66,64,62,62,60,58,56,54,52,50,48,44,42,38,34,30,24,18}, 202Arc39cnt = 79, 203Arc39y[79] = {-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39}, 204Arc39x[79] = {-9,-12,-15,-17,-19,-21,-23,-24,-25,-26,-28,-29,-29,-30,-31,-32,-33,-33,-34,-34,-35,-35,-36,-36,-37,-37,-37,-38,-38,-38,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-38,-38,-38,-37,-37,-37,-36,-36,-35,-35,-34,-34,-33,-33,-32,-31,-30,-29,-29,-28,-26,-25,-24,-23,-21,-19,-17,-15,-12,-9}, 205Arc39rowcnt[79] = {18,24,30,34,38,42,46,48,50,52,56,58,58,60,62,64,66,66,68,68,70,70,72,72,74,74,74,76,76,76,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,76,76,76,74,74,74,72,72,70,70,68,68,66,66,64,62,60,58,58,56,52,50,48,46,42,38,34,30,24,18}, 206Arc40cnt = 81, 207Arc40y[81] = {-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40}, 208Arc40x[81] = {-9,-12,-16,-18,-19,-21,-23,-24,-25,-27,-28,-29,-30,-31,-31,-32,-33,-34,-34,-35,-35,-36,-37,-37,-38,-38,-38,-38,-39,-39,-39,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-39,-39,-39,-38,-38,-38,-38,-37,-37,-36,-35,-35,-34,-34,-33,-32,-31,-31,-30,-29,-28,-27,-25,-24,-23,-21,-19,-18,-16,-12,-9}, 209Arc40rowcnt[81] = {18,24,32,34,38,42,46,48,50,52,56,58,60,62,62,64,66,68,68,70,70,72,74,74,76,76,76,76,78,78,78,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,78,78,78,76,76,76,76,74,74,72,70,70,68,68,66,64,62,62,60,58,56,52,50,48,46,42,38,34,32,24,18}, 210Arc41cnt = 83, 211Arc41y[83] = {-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41}, 212Arc41x[83] = {-9,-13,-16,-18,-20,-22,-23,-25,-26,-27,-28,-29,-30,-31,-32,-33,-34,-34,-35,-36,-36,-37,-37,-38,-38,-39,-39,-39,-40,-40,-40,-40,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-40,-40,-40,-40,-39,-39,-39,-38,-38,-37,-37,-36,-36,-35,-34,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-23,-22,-20,-18,-16,-13,-9}, 213Arc41rowcnt[83] = {18,26,32,36,40,44,46,50,52,54,56,58,60,62,64,66,68,68,70,72,72,74,74,76,76,78,78,78,80,80,80,80,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,80,80,80,80,78,78,78,76,76,74,74,72,72,70,68,68,66,64,62,60,58,56,54,52,50,46,44,40,36,32,26,18}, 214Arc42cnt = 85, 215Arc42y[85] = {-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42}, 216Arc42x[85] = {-9,-13,-16,-18,-20,-22,-24,-25,-26,-27,-29,-30,-31,-32,-32,-33,-34,-35,-36,-36,-37,-37,-38,-38,-39,-39,-40,-40,-40,-41,-41,-41,-41,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-41,-41,-41,-41,-40,-40,-40,-39,-39,-38,-38,-37,-37,-36,-36,-35,-34,-33,-32,-32,-31,-30,-29,-27,-26,-25,-24,-22,-20,-18,-16,-13,-9}, 217Arc42rowcnt[85] = {18,26,32,36,40,44,48,50,52,54,58,60,62,64,64,66,68,70,72,72,74,74,76,76,78,78,80,80,80,82,82,82,82,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,82,82,82,82,80,80,80,78,78,76,76,74,74,72,72,70,68,66,64,64,62,60,58,54,52,50,48,44,40,36,32,26,18}, 218Arc43cnt = 87, 219Arc43y[87] = {-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43}, 220Arc43x[87] = {-10,-13,-16,-18,-20,-22,-24,-25,-27,-28,-29,-30,-31,-32,-33,-34,-35,-35,-36,-37,-37,-38,-38,-39,-39,-40,-40,-41,-41,-41,-42,-42,-42,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-42,-42,-42,-41,-41,-41,-40,-40,-39,-39,-38,-38,-37,-37,-36,-35,-35,-34,-33,-32,-31,-30,-29,-28,-27,-25,-24,-22,-20,-18,-16,-13,-10}, 221Arc43rowcnt[87] = {20,26,32,36,40,44,48,50,54,56,58,60,62,64,66,68,70,70,72,74,74,76,76,78,78,80,80,82,82,82,84,84,84,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,84,84,84,82,82,82,80,80,78,78,76,76,74,74,72,70,70,68,66,64,62,60,58,56,54,50,48,44,40,36,32,26,20}, 222Arc44cnt = 89, 223Arc44y[89] = {-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44}, 224Arc44x[89] = {-10,-13,-16,-19,-20,-22,-24,-26,-27,-28,-29,-31,-32,-33,-33,-34,-35,-36,-37,-37,-38,-38,-39,-39,-40,-41,-41,-41,-42,-42,-42,-43,-43,-43,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-43,-43,-43,-42,-42,-42,-41,-41,-41,-40,-39,-39,-38,-38,-37,-37,-36,-35,-34,-33,-33,-32,-31,-29,-28,-27,-26,-24,-22,-20,-19,-16,-13,-10}, 225Arc44rowcnt[89] = {20,26,32,38,40,44,48,52,54,56,58,62,64,66,66,68,70,72,74,74,76,76,78,78,80,82,82,82,84,84,84,86,86,86,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,86,86,86,84,84,84,82,82,82,80,78,78,76,76,74,74,72,70,68,66,66,64,62,58,56,54,52,48,44,40,38,32,26,20}, 226Arc45cnt = 91, 227Arc45y[91] = {-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45}, 228Arc45x[91] = {-10,-13,-16,-19,-21,-23,-24,-26,-27,-28,-30,-31,-32,-33,-34,-35,-35,-36,-37,-38,-38,-39,-40,-40,-41,-41,-42,-42,-42,-43,-43,-43,-44,-44,-44,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-44,-44,-44,-43,-43,-43,-42,-42,-42,-41,-41,-40,-40,-39,-38,-38,-37,-36,-35,-35,-34,-33,-32,-31,-30,-28,-27,-26,-24,-23,-21,-19,-16,-13,-10}, 229Arc45rowcnt[91] = {20,26,32,38,42,46,48,52,54,56,60,62,64,66,68,70,70,72,74,76,76,78,80,80,82,82,84,84,84,86,86,86,88,88,88,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,88,88,88,86,86,86,84,84,84,82,82,80,80,78,76,76,74,72,70,70,68,66,64,62,60,56,54,52,48,46,42,38,32,26,20}, 230Arc46cnt = 93, 231Arc46y[93] = {-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46}, 232Arc46x[93] = {-10,-13,-16,-19,-21,-23,-25,-26,-28,-29,-30,-31,-32,-33,-34,-35,-36,-37,-38,-38,-39,-40,-40,-41,-41,-42,-42,-43,-43,-43,-44,-44,-44,-45,-45,-45,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-45,-45,-45,-44,-44,-44,-43,-43,-43,-42,-42,-41,-41,-40,-40,-39,-38,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-26,-25,-23,-21,-19,-16,-13,-10}, 233Arc46rowcnt[93] = {20,26,32,38,42,46,50,52,54,56,60,62,64,66,68,70,72,74,76,76,78,80,80,82,82,84,84,86,86,86,88,88,88,90,90,90,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,90,90,90,88,88,88,86,86,86,84,84,82,82,80,80,78,76,76,74,72,70,68,66,64,62,60,56,54,52,50,46,42,38,32,26,20}; 234 235#if 0 236static int Arc2Y[4] = {-1, 0, 1, 2}, Arc2X[4] = {-2, -2, -2, -2}, Arc2Cnt = 4, 237 Arc3Y[12] = {-2, -1, 0, 1, 2, 3, -2, -1, 0, 1, 2, 3}, Arc3Cnt = 12, 238 Arc3X[12] = {-3, -3, -3, -3, -3, -3, -1, -1, -1, -1, -1, -1}, 239 Arc4Y[16] = {-3, -2, -1, 0, 1, 2, 3, 4, -3, -2, -1, 0, 1, 2, 3, 4}, Arc4Cnt = 16, 240 Arc4X[16] = {-3, -4, -4, -4, -4, -4, -4, -3, -1, 0, 0, 0, 0, 0, 0, -1}; 241static int 242Arc5cnt = 10, 243Arc5y[10] = {-4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, 244Arc5x[10] = {-3, -4, -5, -5, -5, -5, -5, -5, -4, -3}, 245Arc5rowcnt[10] = {6,8,10,10,10,10,10,10,8,6}, 246Arc6cnt = 12, 247Arc6y[12] = {-5,-4,-3,-2,-1,0,1,2,3,4,5,6}, 248Arc6x[12] = {-3,-5,-5,-6,-6,-6,-6,-6,-6,-5,-5,-3}, 249Arc6rowcnt[12] = {6,10,10,12,12,12,12,12,12,10,10,6}, 250Arc7cnt = 14, 251Arc7y[14] = {-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7}, 252Arc7x[14] = {-3,-5,-6,-6,-7,-7,-7,-7,-7,-7,-6,-6,-5,-3}, 253Arc7rowcnt[14] = {6,10,12,12,14,14,14,14,14,14,12,12,10,6}, 254Arc8cnt = 16, 255Arc8y[16] = {-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8}, 256Arc8x[16] = {-3,-5,-6,-7,-7,-8,-8,-8,-8,-8,-8,-7,-7,-6,-5,-3}, 257Arc8rowcnt[16] = {6,10,12,14,14,16,16,16,16,16,16,14,14,12,10,6}, 258Arc9cnt = 18, 259Arc9y[18] = {-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9}, 260Arc9x[18] = {-4,-6,-7,-8,-8,-9,-9,-9,-9,-9,-9,-9,-9,-8,-8,-7,-6,-4}, 261Arc9rowcnt[18] = {8,12,14,16,16,18,18,18,18,18,18,18,18,16,16,14,12,8}, 262Arc10cnt = 20, 263Arc10y[20] = {-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10}, 264Arc10x[20] = {-5,-6,-8,-8,-9,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-9,-8,-8,-6,-5}, 265Arc10rowcnt[20] = {10,12,16,16,18,20,20,20,20,20,20,20,20,20,20,18,16,16,12,10}, 266Arc11cnt = 22, 267Arc11y[22] = {-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11}, 268Arc11x[22] = {-5,-6,-8,-9,-9,-10,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-10,-9,-9,-8,-6,-5}, 269Arc11rowcnt[22] = {10,12,16,18,18,20,22,22,22,22,22,22,22,22,22,22,20,18,18,16,12,10}, 270Arc12cnt = 24, 271Arc12y[24] = {-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12}, 272Arc12x[24] = {-5,-7,-8,-9,-10,-11,-11,-12,-12,-12,-12,-12,-12,-12,-12,-12,-12,-11,-11,-10,-9,-8,-7,-5}, 273Arc12rowcnt[24] = {10,14,16,18,20,22,22,24,24,24,24,24,24,24,24,24,24,22,22,20,18,16,14,10}, 274Arc13cnt = 26, 275Arc13y[26] = {-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13}, 276Arc13x[26] = {-5,-7,-9,-10,-11,-11,-12,-12,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-12,-12,-11,-11,-10,-9,-7,-5}, 277Arc13rowcnt[26] = {10,14,18,20,22,22,24,24,26,26,26,26,26,26,26,26,26,26,24,24,22,22,20,18,14,10}, 278Arc14cnt = 28, 279Arc14y[28] = {-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14}, 280Arc14x[28] = {-5,-7,-9,-10,-11,-12,-12,-13,-13,-14,-14,-14,-14,-14,-14,-14,-14,-14,-14,-13,-13,-12,-12,-11,-10,-9,-7,-5}, 281Arc14rowcnt[28] = {10,14,18,20,22,24,24,26,26,28,28,28,28,28,28,28,28,28,28,26,26,24,24,22,20,18,14,10}, 282Arc15cnt = 30, 283Arc15y[30] = {-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, 284Arc15x[30] = {-5,-8,-9,-11,-12,-12,-13,-14,-14,-14,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-14,-14,-14,-13,-12,-12,-11,-9,-8,-5}, 285Arc15rowcnt[30] = {10,16,18,22,24,24,26,28,28,28,30,30,30,30,30,30,30,30,30,30,28,28,28,26,24,24,22,18,16,10}, 286Arc16cnt = 32, 287Arc16y[32] = {-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}, 288Arc16x[32] = {-5,-8,-9,-11,-12,-13,-13,-14,-15,-15,-15,-16,-16,-16,-16,-16,-16,-16,-16,-16,-16,-15,-15,-15,-14,-13,-13,-12,-11,-9,-8,-5}, 289Arc16rowcnt[32] = {10,16,18,22,24,26,26,28,30,30,30,32,32,32,32,32,32,32,32,32,32,30,30,30,28,26,26,24,22,18,16,10}, 290Arc17cnt = 34, 291Arc17y[34] = {-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}, 292Arc17x[34] = {-5,-8,-10,-11,-13,-13,-14,-15,-15,-16,-16,-16,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-16,-16,-16,-15,-15,-14,-13,-13,-11,-10,-8,-5}, 293Arc17rowcnt[34] = {10,16,20,22,26,26,28,30,30,32,32,32,34,34,34,34,34,34,34,34,34,34,32,32,32,30,30,28,26,26,22,20,16,10}, 294Arc18cnt = 36, 295Arc18y[36] = {-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}, 296Arc18x[36] = {-5,-8,-10,-11,-13,-14,-14,-15,-16,-16,-17,-17,-17,-18,-18,-18,-18,-18,-18,-18,-18,-18,-18,-17,-17,-17,-16,-16,-15,-14,-14,-13,-11,-10,-8,-5}, 297Arc18rowcnt[36] = {10,16,20,22,26,28,28,30,32,32,34,34,34,36,36,36,36,36,36,36,36,36,36,34,34,34,32,32,30,28,28,26,22,20,16,10}, 298Arc19cnt = 38, 299Arc19y[38] = {-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}, 300Arc19x[38] = {-5,-9,-10,-12,-13,-14,-15,-16,-16,-17,-18,-18,-18,-18,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-18,-18,-18,-18,-17,-16,-16,-15,-14,-13,-12,-10,-9,-5}, 301Arc19rowcnt[38] = {10,18,20,24,26,28,30,32,32,34,36,36,36,36,38,38,38,38,38,38,38,38,38,38,36,36,36,36,34,32,32,30,28,26,24,20,18,10}, 302Arc20cnt = 40, 303Arc20y[40] = {-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}, 304Arc20x[40] = {-5,-9,-10,-12,-13,-15,-15,-16,-17,-17,-18,-19,-19,-19,-19,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-19,-19,-19,-19,-18,-17,-17,-16,-15,-15,-13,-12,-10,-9,-5}, 305Arc20rowcnt[40] = {10,18,20,24,26,30,30,32,34,34,36,38,38,38,38,40,40,40,40,40,40,40,40,40,40,38,38,38,38,36,34,34,32,30,30,26,24,20,18,10}, 306Arc21cnt = 42, 307Arc21y[42] = {-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21}, 308Arc21x[42] = {-5,-9,-11,-12,-14,-15,-16,-17,-17,-18,-19,-19,-20,-20,-20,-20,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-20,-20,-20,-20,-19,-19,-18,-17,-17,-16,-15,-14,-12,-11,-9,-5}, 309Arc21rowcnt[42] = {10,18,22,24,28,30,32,34,34,36,38,38,40,40,40,40,42,42,42,42,42,42,42,42,42,42,40,40,40,40,38,38,36,34,34,32,30,28,24,22,18,10}, 310Arc22cnt = 44, 311Arc22y[44] = {-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22}, 312Arc22x[44] = {-5,-9,-11,-12,-14,-15,-16,-17,-18,-18,-19,-20,-20,-21,-21,-21,-21,-22,-22,-22,-22,-22,-22,-22,-22,-22,-22,-21,-21,-21,-21,-20,-20,-19,-18,-18,-17,-16,-15,-14,-12,-11,-9,-5}, 313Arc22rowcnt[44] = {10,18,22,24,28,30,32,34,36,36,38,40,40,42,42,42,42,44,44,44,44,44,44,44,44,44,44,42,42,42,42,40,40,38,36,36,34,32,30,28,24,22,18,10}, 314Arc23cnt = 46, 315Arc23y[46] = {-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}, 316Arc23x[46] = {-5,-10,-11,-13,-14,-16,-17,-18,-18,-19,-20,-20,-21,-22,-22,-22,-22,-22,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-22,-22,-22,-22,-22,-21,-20,-20,-19,-18,-18,-17,-16,-14,-13,-11,-10,-5}, 317Arc23rowcnt[46] = {10,20,22,26,28,32,34,36,36,38,40,40,42,44,44,44,44,44,46,46,46,46,46,46,46,46,46,46,44,44,44,44,44,42,40,40,38,36,36,34,32,28,26,22,20,10}, 318Arc24cnt = 48, 319Arc24y[48] = {-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}, 320Arc24x[48] = {-5,-10,-11,-13,-14,-16,-17,-18,-19,-19,-20,-21,-21,-22,-23,-23,-23,-23,-23,-24,-24,-24,-24,-24,-24,-24,-24,-24,-24,-23,-23,-23,-23,-23,-22,-21,-21,-20,-19,-19,-18,-17,-16,-14,-13,-11,-10,-5}, 321Arc24rowcnt[48] = {10,20,22,26,28,32,34,36,38,38,40,42,42,44,46,46,46,46,46,48,48,48,48,48,48,48,48,48,48,46,46,46,46,46,44,42,42,40,38,38,36,34,32,28,26,22,20,10}, 322Arc25cnt = 50, 323Arc25y[50] = {-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25}, 324Arc25x[50] = {-5,-10,-12,-13,-15,-16,-18,-19,-19,-20,-21,-21,-22,-23,-23,-24,-24,-24,-24,-24,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-24,-24,-24,-24,-24,-23,-23,-22,-21,-21,-20,-19,-19,-18,-16,-15,-13,-12,-10,-5}, 325Arc25rowcnt[50] = {10,20,24,26,30,32,36,38,38,40,42,42,44,46,46,48,48,48,48,48,50,50,50,50,50,50,50,50,50,50,48,48,48,48,48,46,46,44,42,42,40,38,38,36,32,30,26,24,20,10}, 326Arc26cnt = 52, 327Arc26y[52] = {-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26}, 328Arc26x[52] = {-5,-10,-12,-14,-15,-16,-18,-19,-20,-20,-21,-22,-23,-23,-24,-24,-25,-25,-25,-25,-25,-26,-26,-26,-26,-26,-26,-26,-26,-26,-26,-25,-25,-25,-25,-25,-24,-24,-23,-23,-22,-21,-20,-20,-19,-18,-16,-15,-14,-12,-10,-5}, 329Arc26rowcnt[52] = {10,20,24,28,30,32,36,38,40,40,42,44,46,46,48,48,50,50,50,50,50,52,52,52,52,52,52,52,52,52,52,50,50,50,50,50,48,48,46,46,44,42,40,40,38,36,32,30,28,24,20,10}, 330Arc27cnt = 54, 331Arc27y[54] = {-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27}, 332Arc27x[54] = {-5,-10,-12,-14,-15,-17,-18,-20,-20,-21,-22,-22,-23,-24,-24,-25,-25,-26,-26,-26,-26,-26,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-26,-26,-26,-26,-26,-25,-25,-24,-24,-23,-22,-22,-21,-20,-20,-18,-17,-15,-14,-12,-10,-5}, 333Arc27rowcnt[54] = {10,20,24,28,30,34,36,40,40,42,44,44,46,48,48,50,50,52,52,52,52,52,54,54,54,54,54,54,54,54,54,54,52,52,52,52,52,50,50,48,48,46,44,44,42,40,40,36,34,30,28,24,20,10}, 334Arc28cnt = 56, 335Arc28y[56] = {-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28}, 336Arc28x[56] = {-5,-10,-13,-14,-16,-17,-19,-20,-21,-22,-22,-23,-24,-24,-25,-26,-26,-26,-27,-27,-27,-27,-27,-28,-28,-28,-28,-28,-28,-28,-28,-28,-28,-27,-27,-27,-27,-27,-26,-26,-26,-25,-24,-24,-23,-22,-22,-21,-20,-19,-17,-16,-14,-13,-10,-5}, 337Arc28rowcnt[56] = {10,20,26,28,32,34,38,40,42,44,44,46,48,48,50,52,52,52,54,54,54,54,54,56,56,56,56,56,56,56,56,56,56,54,54,54,54,54,52,52,52,50,48,48,46,44,44,42,40,38,34,32,28,26,20,10}, 338Arc29cnt = 58, 339Arc29y[58] = {-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29}, 340Arc29x[58] = {-5,-10,-13,-14,-16,-17,-19,-20,-21,-22,-23,-23,-24,-25,-25,-26,-27,-27,-27,-28,-28,-28,-28,-28,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-28,-28,-28,-28,-28,-27,-27,-27,-26,-25,-25,-24,-23,-23,-22,-21,-20,-19,-17,-16,-14,-13,-10,-5}, 341Arc29rowcnt[58] = {10,20,26,28,32,34,38,40,42,44,46,46,48,50,50,52,54,54,54,56,56,56,56,56,58,58,58,58,58,58,58,58,58,58,56,56,56,56,56,54,54,54,52,50,50,48,46,46,44,42,40,38,34,32,28,26,20,10}, 342Arc30cnt = 60, 343Arc30y[60] = {-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}, 344Arc30x[60] = {-5,-10,-13,-15,-16,-18,-19,-21,-22,-23,-23,-24,-25,-25,-26,-27,-27,-28,-28,-28,-29,-29,-29,-29,-29,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-29,-29,-29,-29,-29,-28,-28,-28,-27,-27,-26,-25,-25,-24,-23,-23,-22,-21,-19,-18,-16,-15,-13,-10,-5}, 345Arc30rowcnt[60] = {10,20,26,30,32,36,38,42,44,46,46,48,50,50,52,54,54,56,56,56,58,58,58,58,58,60,60,60,60,60,60,60,60,60,60,58,58,58,58,58,56,56,56,54,54,52,50,50,48,46,46,44,42,38,36,32,30,26,20,10}, 346Arc31cnt = 62, 347Arc31y[62] = {-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}, 348Arc31x[62] = {-5,-10,-13,-15,-16,-18,-19,-21,-22,-23,-24,-24,-25,-26,-26,-27,-28,-28,-29,-29,-29,-30,-30,-30,-30,-30,-31,-31,-31,-31,-31,-31,-31,-31,-31,-31,-30,-30,-30,-30,-30,-29,-29,-29,-28,-28,-27,-26,-26,-25,-24,-24,-23,-22,-21,-19,-18,-16,-15,-13,-10,-5}, 349Arc31rowcnt[62] = {10,20,26,30,32,36,38,42,44,46,48,48,50,52,52,54,56,56,58,58,58,60,60,60,60,60,62,62,62,62,62,62,62,62,62,62,60,60,60,60,60,58,58,58,56,56,54,52,52,50,48,48,46,44,42,38,36,32,30,26,20,10}, 350Arc32cnt = 64, 351Arc32y[64] = {-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}, 352Arc32x[64] = {-5,-10,-14,-15,-17,-18,-20,-21,-23,-24,-24,-25,-26,-26,-27,-28,-28,-29,-30,-30,-30,-30,-31,-31,-31,-31,-31,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-31,-31,-31,-31,-31,-30,-30,-30,-30,-29,-28,-28,-27,-26,-26,-25,-24,-24,-23,-21,-20,-18,-17,-15,-14,-10,-5}, 353Arc32rowcnt[64] = {10,20,28,30,34,36,40,42,46,48,48,50,52,52,54,56,56,58,60,60,60,60,62,62,62,62,62,64,64,64,64,64,64,64,64,64,64,62,62,62,62,62,60,60,60,60,58,56,56,54,52,52,50,48,48,46,42,40,36,34,30,28,20,10}, 354Arc33cnt = 66, 355Arc33y[66] = {-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33}, 356Arc33x[66] = {-5,-10,-14,-15,-17,-18,-20,-21,-23,-24,-25,-25,-26,-27,-27,-28,-29,-29,-30,-31,-31,-31,-31,-32,-32,-32,-32,-32,-33,-33,-33,-33,-33,-33,-33,-33,-33,-33,-32,-32,-32,-32,-32,-31,-31,-31,-31,-30,-29,-29,-28,-27,-27,-26,-25,-25,-24,-23,-21,-20,-18,-17,-15,-14,-10,-5}, 357Arc33rowcnt[66] = {10,20,28,30,34,36,40,42,46,48,50,50,52,54,54,56,58,58,60,62,62,62,62,64,64,64,64,64,66,66,66,66,66,66,66,66,66,66,64,64,64,64,64,62,62,62,62,60,58,58,56,54,54,52,50,50,48,46,42,40,36,34,30,28,20,10}, 358Arc34cnt = 68, 359Arc34y[68] = {-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34}, 360Arc34x[68] = {-5,-10,-14,-16,-18,-20,-21,-22,-23,-25,-25,-26,-27,-28,-29,-29,-30,-30,-31,-31,-32,-32,-32,-32,-33,-33,-33,-33,-33,-34,-34,-34,-34,-34,-34,-34,-34,-34,-34,-33,-33,-33,-33,-33,-32,-32,-32,-32,-31,-31,-30,-30,-29,-29,-28,-27,-26,-25,-25,-23,-22,-21,-20,-18,-16,-14,-10,-5}, 361Arc34rowcnt[68] = {10,20,28,32,36,40,42,44,46,50,50,52,54,56,58,58,60,60,62,62,64,64,64,64,66,66,66,66,66,68,68,68,68,68,68,68,68,68,68,66,66,66,66,66,64,64,64,64,62,62,60,60,58,58,56,54,52,50,50,46,44,42,40,36,32,28,20,10}, 362Arc35cnt = 70, 363Arc35y[70] = {-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35}, 364Arc35x[70] = {-5,-10,-15,-16,-18,-20,-21,-23,-24,-25,-26,-27,-28,-28,-29,-30,-30,-31,-31,-32,-33,-33,-33,-33,-33,-34,-34,-34,-34,-34,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-34,-34,-34,-34,-34,-33,-33,-33,-33,-33,-32,-31,-31,-30,-30,-29,-28,-28,-27,-26,-25,-24,-23,-21,-20,-18,-16,-15,-10,-5}, 365Arc35rowcnt[70] = {10,20,30,32,34,40,42,46,48,50,52,54,56,56,58,60,60,62,62,64,66,66,66,66,66,68,68,68,68,68,70,70,70,70,70,70,70,70,70,70,68,68,68,68,68,66,66,66,66,66,64,62,62,60,60,58,56,56,54,52,50,48,46,42,40,34,32,30,20,10}, 366Arc36cnt = 72, 367Arc36y[72] = {-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36}, 368Arc36x[72] = {-9,-12,-15,-17,-18,-20,-22,-23,-24,-25,-26,-27,-28,-29,-30,-30,-31,-31,-32,-33,-33,-34,-34,-34,-35,-35,-35,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-36,-35,-35,-35,-34,-34,-34,-33,-33,-32,-31,-31,-30,-30,-29,-28,-27,-26,-25,-24,-23,-22,-20,-18,-17,-15,-12,-9}, 369Arc36rowcnt[72] = {18,24,30,34,38,40,44,46,48,50,52,54,56,58,60,60,62,62,64,66,66,68,68,68,70,70,70,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,70,70,70,68,68,68,66,66,64,62,62,60,60,58,56,54,52,50,48,46,44,40,38,34,30,24,18}, 370Arc37cnt = 74, 371Arc37y[74] = {-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37}, 372Arc37x[74] = {-9,-12,-15,-17,-19,-21,-22,-23,-24,-26,-27,-28,-28,-29,-30,-31,-32,-32,-33,-33,-34,-34,-35,-35,-35,-36,-36,-36,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-37,-36,-36,-36,-35,-35,-35,-34,-34,-33,-33,-32,-32,-31,-30,-29,-28,-28,-27,-26,-24,-23,-22,-21,-19,-17,-15,-12,-9}, 373Arc37rowcnt[74] = {18,24,30,34,38,42,44,46,48,52,54,56,56,58,60,62,64,64,66,66,68,68,70,70,70,72,72,72,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,72,72,72,70,70,70,68,68,66,66,64,64,62,60,58,56,56,54,52,48,46,44,42,38,34,30,24,18}, 374Arc38cnt = 76, 375Arc38y[76] = {-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38}, 376Arc38x[76] = {-9,-12,-15,-17,-19,-21,-22,-24,-25,-26,-27,-28,-29,-30,-31,-31,-32,-33,-33,-34,-34,-35,-35,-36,-36,-36,-37,-37,-37,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-38,-37,-37,-37,-36,-36,-36,-35,-35,-34,-34,-33,-33,-32,-31,-31,-30,-29,-28,-27,-26,-25,-24,-22,-21,-19,-17,-15,-12,-9}, 377Arc38rowcnt[76] = {18,24,30,34,38,42,44,48,50,52,54,56,58,60,62,62,64,66,66,68,68,70,70,72,72,72,74,74,74,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,74,74,74,72,72,72,70,70,68,68,66,66,64,62,62,60,58,56,54,52,50,48,44,42,38,34,30,24,18}, 378Arc39cnt = 78, 379Arc39y[78] = {-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39}, 380Arc39x[78] = {-9,-12,-15,-17,-19,-21,-23,-24,-25,-26,-28,-29,-29,-30,-31,-32,-33,-33,-34,-34,-35,-35,-36,-36,-37,-37,-37,-38,-38,-38,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-39,-38,-38,-38,-37,-37,-37,-36,-36,-35,-35,-34,-34,-33,-33,-32,-31,-30,-29,-29,-28,-26,-25,-24,-23,-21,-19,-17,-15,-12,-9}, 381Arc39rowcnt[78] = {18,24,30,34,38,42,46,48,50,52,56,58,58,60,62,64,66,66,68,68,70,70,72,72,74,74,74,76,76,76,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,76,76,76,74,74,74,72,72,70,70,68,68,66,66,64,62,60,58,58,56,52,50,48,46,42,38,34,30,24,18}, 382Arc40cnt = 80, 383Arc40y[80] = {-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40}, 384Arc40x[80] = {-9,-12,-16,-18,-19,-21,-23,-24,-25,-27,-28,-29,-30,-31,-31,-32,-33,-34,-34,-35,-35,-36,-37,-37,-38,-38,-38,-38,-39,-39,-39,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-39,-39,-39,-38,-38,-38,-38,-37,-37,-36,-35,-35,-34,-34,-33,-32,-31,-31,-30,-29,-28,-27,-25,-24,-23,-21,-19,-18,-16,-12,-9}, 385Arc40rowcnt[80] = {18,24,32,34,38,42,46,48,50,52,56,58,60,62,62,64,66,68,68,70,70,72,74,74,76,76,76,76,78,78,78,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,78,78,78,76,76,76,76,74,74,72,70,70,68,68,66,64,62,62,60,58,56,52,50,48,46,42,38,34,32,24,18}, 386Arc41cnt = 82, 387Arc41y[82] = {-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41}, 388Arc41x[82] = {-9,-13,-16,-18,-20,-22,-23,-25,-26,-27,-28,-29,-30,-31,-32,-33,-34,-34,-35,-36,-36,-37,-37,-38,-38,-39,-39,-39,-40,-40,-40,-40,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-41,-40,-40,-40,-40,-39,-39,-39,-38,-38,-37,-37,-36,-36,-35,-34,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-23,-22,-20,-18,-16,-13,-9}, 389Arc41rowcnt[82] = {18,26,32,36,40,44,46,50,52,54,56,58,60,62,64,66,68,68,70,72,72,74,74,76,76,78,78,78,80,80,80,80,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,80,80,80,80,78,78,78,76,76,74,74,72,72,70,68,68,66,64,62,60,58,56,54,52,50,46,44,40,36,32,26,18}, 390Arc42cnt = 84, 391Arc42y[84] = {-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42}, 392Arc42x[84] = {-9,-13,-16,-18,-20,-22,-24,-25,-26,-27,-29,-30,-31,-32,-32,-33,-34,-35,-36,-36,-37,-37,-38,-38,-39,-39,-40,-40,-40,-41,-41,-41,-41,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-42,-41,-41,-41,-41,-40,-40,-40,-39,-39,-38,-38,-37,-37,-36,-36,-35,-34,-33,-32,-32,-31,-30,-29,-27,-26,-25,-24,-22,-20,-18,-16,-13,-9}, 393Arc42rowcnt[84] = {18,26,32,36,40,44,48,50,52,54,58,60,62,64,64,66,68,70,72,72,74,74,76,76,78,78,80,80,80,82,82,82,82,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,82,82,82,82,80,80,80,78,78,76,76,74,74,72,72,70,68,66,64,64,62,60,58,54,52,50,48,44,40,36,32,26,18}, 394Arc43cnt = 86, 395Arc43y[86] = {-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43}, 396Arc43x[86] = {-10,-13,-16,-18,-20,-22,-24,-25,-27,-28,-29,-30,-31,-32,-33,-34,-35,-35,-36,-37,-37,-38,-38,-39,-39,-40,-40,-41,-41,-41,-42,-42,-42,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-43,-42,-42,-42,-41,-41,-41,-40,-40,-39,-39,-38,-38,-37,-37,-36,-35,-35,-34,-33,-32,-31,-30,-29,-28,-27,-25,-24,-22,-20,-18,-16,-13,-10}, 397Arc43rowcnt[86] = {20,26,32,36,40,44,48,50,54,56,58,60,62,64,66,68,70,70,72,74,74,76,76,78,78,80,80,82,82,82,84,84,84,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,84,84,84,82,82,82,80,80,78,78,76,76,74,74,72,70,70,68,66,64,62,60,58,56,54,50,48,44,40,36,32,26,20}, 398Arc44cnt = 88, 399Arc44y[88] = {-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44}, 400Arc44x[88] = {-10,-13,-16,-19,-20,-22,-24,-26,-27,-28,-29,-31,-32,-33,-33,-34,-35,-36,-37,-37,-38,-38,-39,-39,-40,-41,-41,-41,-42,-42,-42,-43,-43,-43,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-44,-43,-43,-43,-42,-42,-42,-41,-41,-41,-40,-39,-39,-38,-38,-37,-37,-36,-35,-34,-33,-33,-32,-31,-29,-28,-27,-26,-24,-22,-20,-19,-16,-13,-10}, 401Arc44rowcnt[88] = {20,26,32,38,40,44,48,52,54,56,58,62,64,66,66,68,70,72,74,74,76,76,78,78,80,82,82,82,84,84,84,86,86,86,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,86,86,86,84,84,84,82,82,82,80,78,78,76,76,74,74,72,70,68,66,66,64,62,58,56,54,52,48,44,40,38,32,26,20}, 402Arc45cnt = 90, 403Arc45y[90] = {-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45}, 404Arc45x[90] = {-10,-13,-16,-19,-21,-23,-24,-26,-27,-28,-30,-31,-32,-33,-34,-35,-35,-36,-37,-38,-38,-39,-40,-40,-41,-41,-42,-42,-42,-43,-43,-43,-44,-44,-44,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-45,-44,-44,-44,-43,-43,-43,-42,-42,-42,-41,-41,-40,-40,-39,-38,-38,-37,-36,-35,-35,-34,-33,-32,-31,-30,-28,-27,-26,-24,-23,-21,-19,-16,-13,-10}, 405Arc45rowcnt[90] = {20,26,32,38,42,46,48,52,54,56,60,62,64,66,68,70,70,72,74,76,76,78,80,80,82,82,84,84,84,86,86,86,88,88,88,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,88,88,88,86,86,86,84,84,84,82,82,80,80,78,76,76,74,72,70,70,68,66,64,62,60,56,54,52,48,46,42,38,32,26,20}, 406Arc46cnt = 92, 407Arc46y[92] = {-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46}, 408Arc46x[92] = {-10,-13,-16,-19,-21,-23,-25,-26,-28,-29,-30,-31,-32,-33,-34,-35,-36,-37,-38,-38,-39,-40,-40,-41,-41,-42,-42,-43,-43,-43,-44,-44,-44,-45,-45,-45,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-46,-45,-45,-45,-44,-44,-44,-43,-43,-43,-42,-42,-41,-41,-40,-40,-39,-38,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-26,-25,-23,-21,-19,-16,-13,-10}, 409Arc46rowcnt[92] = {20,26,32,38,42,46,50,52,54,56,60,62,64,66,68,70,72,74,76,76,78,80,80,82,82,84,84,86,86,86,88,88,88,90,90,90,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,90,90,90,88,88,88,86,86,86,84,84,82,82,80,80,78,76,76,74,72,70,68,66,64,62,60,56,54,52,50,46,42,38,32,26,20}; 410#endif 411 412/* 413 * 4 2 6 414 * 0 8 1 415 * 5 3 7 416 */ 417 418/* pixel(nxp) has left, right, up or down a white pixel at its side -> return YES 419 */ 420#define SameGradients(grad, grad0) \ 421( ((Diff(grad.y, 0)<TOLERANCE || Diff(grad0.y, 0)<TOLERANCE) && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.01 && \ 422 ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0))) || \ 423 ((Diff(grad.x, 0)<TOLERANCE || Diff(grad0.x, 0)<TOLERANCE) && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.01 && \ 424 ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0))) || \ 425 (Abs(grad.x) < Abs(grad.y) && grad.y != 0 && grad0.y != 0 && ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0)) &&\ 426 Diff(grad.x, 0)>TOLERANCE && Diff(grad0.x, 0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.03) || \ 427 (Abs(grad.x) > Abs(grad.y) && grad.x != 0 && grad0.x != 0 && ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0)) &&\ 428 Diff(grad.y, 0)>TOLERANCE && Diff(grad0.y, 0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.03) || \ 429 (Diff(grad.x, 0.0)>TOLERANCE && Diff(grad0.x, 0.0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.01 && \ 430 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 431 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) || \ 432 (Diff(grad.y, 0.0)>TOLERANCE && Diff(grad0.y, 0.0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.01 && \ 433 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 434 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) ) 435 436#define NearlySameGradients(grad, grad0) \ 437( ((Diff(grad.y, 0)<TOLERANCE || Diff(grad0.y, 0)<TOLERANCE) && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.3 && \ 438 ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0))) || \ 439 ((Diff(grad.x, 0)<TOLERANCE || Diff(grad0.x, 0)<TOLERANCE) && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.3 && \ 440 ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0))) || \ 441 (Abs(grad.x) < Abs(grad.y) && grad.y != 0 && grad0.y != 0 && ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0)) &&\ 442 Diff(grad.x, 0)>TOLERANCE && Diff(grad0.x, 0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.3) || \ 443 (Abs(grad.x) > Abs(grad.y) && grad.x != 0 && grad0.x != 0 && ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0)) &&\ 444 Diff(grad.y, 0)>TOLERANCE && Diff(grad0.y, 0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.3) || \ 445 (Diff(grad.x, 0.0)>TOLERANCE && Diff(grad0.x, 0.0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.25 && \ 446 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 447 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) || \ 448 (Diff(grad.y, 0.0)>TOLERANCE && Diff(grad0.y, 0.0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.25 && \ 449 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 450 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) ) 451 452#define NNSameGradients(grad, grad0) \ 453( ((Diff(grad.y, 0)<TOLERANCE || Diff(grad0.y, 0)<TOLERANCE) && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.5 && \ 454 ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0))) || \ 455 ((Diff(grad.x, 0)<TOLERANCE || Diff(grad0.x, 0)<TOLERANCE) && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.5 && \ 456 ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0))) || \ 457 (Abs(grad.x) < Abs(grad.y) && grad.y != 0 && grad0.y != 0 && ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0)) &&\ 458 Diff(grad.x, 0)>TOLERANCE && Diff(grad0.x, 0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.5) || \ 459 (Abs(grad.x) > Abs(grad.y) && grad.x != 0 && grad0.x != 0 && ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0)) &&\ 460 Diff(grad.y, 0)>TOLERANCE && Diff(grad0.y, 0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.5) || \ 461 (Diff(grad.x, 0.0)>TOLERANCE && Diff(grad0.x, 0.0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.5 && \ 462 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 463 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) || \ 464 (Diff(grad.y, 0.0)>TOLERANCE && Diff(grad0.y, 0.0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.5 && \ 465 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 466 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) ) 467 468#define NNNNSameGradients(grad, grad0) \ 469( ((Diff(grad.y, 0)<TOLERANCE || Diff(grad0.y, 0)<TOLERANCE) && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.65 && \ 470 ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0))) || \ 471 ((Diff(grad.x, 0)<TOLERANCE || Diff(grad0.x, 0)<TOLERANCE) && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.65 && \ 472 ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0))) || \ 473 (Abs(grad.x) < Abs(grad.y) && grad.y != 0 && grad0.y != 0 && ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0)) &&\ 474 Diff(grad.x, 0)>TOLERANCE && Diff(grad0.x, 0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.65) || \ 475 (Abs(grad.x) > Abs(grad.y) && grad.x != 0 && grad0.x != 0 && ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0)) &&\ 476 Diff(grad.y, 0)>TOLERANCE && Diff(grad0.y, 0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.65) || \ 477 (Diff(grad.x, 0.0)>TOLERANCE && Diff(grad0.x, 0.0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 0.65 && \ 478 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 479 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) || \ 480 (Diff(grad.y, 0.0)>TOLERANCE && Diff(grad0.y, 0.0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 0.65 && \ 481 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 482 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) ) 483 484- (void)invertData 485{ int i; 486 unsigned char everything=255; 487 488 for (i=0; i<size; i++) 489 *(data+i) ^= everything; 490} 491 492/* modified: 02.02.00 493 * 494 */ 495-(void)drawArcInDataAt:(int)byteX radius:(int)radius color:(unsigned char)col 496{ int j; 497 498 switch (radius) 499 { 500 case 0: return; 501 case 1: 502 *((WORD*)(data+byteX-bytesPerRow-1)) = 0; // intBlack 503 *((WORD*)(data+byteX-1)) = 0; // intBlack 504 *((WORD*)(data+byteX+bytesPerRow-1)) = 0; // intBlack 505 *((WORD*)(data+byteX-bytesPerRow)) = 0; // intBlack 506 *((WORD*)(data+byteX)) = 0; // intBlack 507 *((WORD*)(data+byteX+bytesPerRow)) = 0; // intBlack 508 break; 509 case 2: 510 for (j=0; j<Arc2cnt; j++) 511 memset((data+byteX+(Arc2y[j]*bytesPerRow)+(Arc2x[j])), col, Arc2rowcnt[j]); 512 break; 513 case 3: 514 for (j=0; j<Arc3cnt; j++) 515 memset((data+byteX+(Arc3y[j]*bytesPerRow)+(Arc3x[j])), col, Arc3rowcnt[j]); 516 break; 517 case 4: 518 for (j=0; j<Arc4cnt; j++) 519 memset((data+byteX+(Arc4y[j]*bytesPerRow)+(Arc4x[j])), col, Arc4rowcnt[j]); 520 break; 521 case 5: 522 for (j=0; j<Arc5cnt; j++) 523 memset((data+byteX+(Arc5y[j]*bytesPerRow)+(Arc5x[j])), col, Arc5rowcnt[j]); 524 break; 525 case 6: 526 for (j=0; j<Arc6cnt; j++) 527 memset((data+byteX+(Arc6y[j]*bytesPerRow)+(Arc6x[j])), col, Arc6rowcnt[j]); 528 break; 529 case 7: 530 for (j=0; j<Arc7cnt; j++) 531 memset((data+byteX+(Arc7y[j]*bytesPerRow)+(Arc7x[j])), col, Arc7rowcnt[j]); 532 break; 533 case 8: 534 for (j=0; j<Arc8cnt; j++) 535 memset((data+byteX+(Arc8y[j]*bytesPerRow)+(Arc8x[j])), col, Arc8rowcnt[j]); 536 break; 537 case 9: 538 for (j=0; j<Arc9cnt; j++) 539 memset((data+byteX+(Arc9y[j]*bytesPerRow)+(Arc9x[j])), col, Arc9rowcnt[j]); 540 break; 541 case 10: 542 for (j=0; j<Arc10cnt; j++) 543 memset((data+byteX+(Arc10y[j]*bytesPerRow)+(Arc10x[j])), col, Arc10rowcnt[j]); 544 break; 545 case 11: 546 for (j=0; j<Arc11cnt; j++) 547 memset((data+byteX+(Arc11y[j]*bytesPerRow)+(Arc11x[j])), col, Arc11rowcnt[j]); 548 break; 549 case 12: 550 for (j=0; j<Arc12cnt; j++) 551 memset((data+byteX+(Arc12y[j]*bytesPerRow)+(Arc12x[j])), col, Arc12rowcnt[j]); 552 break; 553 case 13: 554 for (j=0; j<Arc13cnt; j++) 555 memset((data+byteX+(Arc13y[j]*bytesPerRow)+(Arc13x[j])), col, Arc13rowcnt[j]); 556 break; 557 case 14: 558 for (j=0; j<Arc14cnt; j++) 559 memset((data+byteX+(Arc14y[j]*bytesPerRow)+(Arc14x[j])), col, Arc14rowcnt[j]); 560 break; 561 case 15: 562 for (j=0; j<Arc15cnt; j++) 563 memset((data+byteX+(Arc15y[j]*bytesPerRow)+(Arc15x[j])), col, Arc15rowcnt[j]+1); 564 break; 565 case 16: 566 for (j=0; j<Arc16cnt; j++) 567 memset((data+byteX+(Arc16y[j]*bytesPerRow)+(Arc16x[j])), col, Arc16rowcnt[j]+1); 568 break; 569 case 17: 570 for (j=0; j<Arc17cnt; j++) 571 memset((data+byteX+(Arc17y[j]*bytesPerRow)+(Arc17x[j])), col, Arc17rowcnt[j]+1); 572 break; 573 case 18: 574 for (j=0; j<Arc18cnt; j++) 575 memset((data+byteX+(Arc18y[j]*bytesPerRow)+(Arc18x[j])), col, Arc18rowcnt[j]+1); 576 break; 577 case 19: 578 for (j=0; j<Arc19cnt; j++) 579 memset((data+byteX+(Arc19y[j]*bytesPerRow)+(Arc19x[j])), col, Arc19rowcnt[j]+1); 580 break; 581 case 20: 582 for (j=0; j<Arc20cnt; j++) 583 memset((data+byteX+(Arc20y[j]*bytesPerRow)+(Arc20x[j])), col, Arc20rowcnt[j]+1); 584 break; 585 case 21: 586 for (j=0; j<Arc21cnt; j++) 587 memset((data+byteX+(Arc21y[j]*bytesPerRow)+(Arc21x[j])), col, Arc21rowcnt[j]+1); 588 break; 589 case 22: 590 for (j=0; j<Arc22cnt; j++) 591 memset((data+byteX+(Arc22y[j]*bytesPerRow)+(Arc22x[j])), col, Arc22rowcnt[j]+1); 592 break; 593 case 23: 594 for (j=0; j<Arc23cnt; j++) 595 memset((data+byteX+(Arc23y[j]*bytesPerRow)+(Arc23x[j])), col, Arc23rowcnt[j]+1); 596 break; 597 case 24: 598 for (j=0; j<Arc24cnt; j++) 599 memset((data+byteX+(Arc24y[j]*bytesPerRow)+(Arc24x[j])), col, Arc24rowcnt[j]+1); 600 break; 601 case 25: 602 for (j=0; j<Arc25cnt; j++) 603 memset((data+byteX+(Arc25y[j]*bytesPerRow)+(Arc25x[j])), col, Arc25rowcnt[j]+1); 604 break; 605 case 26: 606 for (j=0; j<Arc26cnt; j++) 607 memset((data+byteX+(Arc26y[j]*bytesPerRow)+(Arc26x[j])), col, Arc26rowcnt[j]+1); 608 break; 609 case 27: 610 for (j=0; j<Arc27cnt; j++) 611 memset((data+byteX+(Arc27y[j]*bytesPerRow)+(Arc27x[j])), col, Arc27rowcnt[j]+1); 612 break; 613 case 28: 614 for (j=0; j<Arc28cnt; j++) 615 memset((data+byteX+(Arc28y[j]*bytesPerRow)+(Arc28x[j])), col, Arc28rowcnt[j]+1); 616 break; 617 case 29: 618 for (j=0; j<Arc29cnt; j++) 619 memset((data+byteX+(Arc29y[j]*bytesPerRow)+(Arc29x[j])), col, Arc29rowcnt[j]+1); 620 break; 621 case 30: 622 for (j=0; j<Arc30cnt; j++) 623 memset((data+byteX+(Arc30y[j]*bytesPerRow)+(Arc30x[j])), col, Arc30rowcnt[j]+1); 624 break; 625 case 31: 626 for (j=0; j<Arc31cnt; j++) 627 memset((data+byteX+(Arc31y[j]*bytesPerRow)+(Arc31x[j])), col, Arc31rowcnt[j]+1); 628 break; 629 case 32: 630 for (j=0; j<Arc32cnt; j++) 631 memset((data+byteX+(Arc32y[j]*bytesPerRow)+(Arc32x[j])), col, Arc32rowcnt[j]+1); 632 break; 633 case 33: 634 for (j=0; j<Arc33cnt; j++) 635 memset((data+byteX+(Arc33y[j]*bytesPerRow)+(Arc33x[j])), col, Arc33rowcnt[j]+1); 636 break; 637 case 34: 638 for (j=0; j<Arc34cnt; j++) 639 memset((data+byteX+(Arc34y[j]*bytesPerRow)+(Arc34x[j])), col, Arc34rowcnt[j]+1); 640 break; 641 case 35: 642 for (j=0; j<Arc35cnt; j++) 643 memset((data+byteX+(Arc35y[j]*bytesPerRow)+(Arc35x[j])), col, Arc35rowcnt[j]+1); 644 break; 645 case 36: 646 for (j=0; j<Arc36cnt; j++) 647 memset((data+byteX+(Arc36y[j]*bytesPerRow)+(Arc36x[j])), col, Arc36rowcnt[j]+1); 648 break; 649 case 37: 650 for (j=0; j<Arc37cnt; j++) 651 memset((data+byteX+(Arc37y[j]*bytesPerRow)+(Arc37x[j])), col, Arc37rowcnt[j]+1); 652 break; 653 case 38: 654 for (j=0; j<Arc38cnt; j++) 655 memset((data+byteX+(Arc38y[j]*bytesPerRow)+(Arc38x[j])), col, Arc38rowcnt[j]+1); 656 break; 657 case 39: 658 for (j=0; j<Arc39cnt; j++) 659 memset((data+byteX+(Arc39y[j]*bytesPerRow)+(Arc39x[j])), col, Arc39rowcnt[j]+1); 660 break; 661 case 40: 662 for (j=0; j<Arc40cnt; j++) 663 memset((data+byteX+(Arc40y[j]*bytesPerRow)+(Arc40x[j])), col, Arc40rowcnt[j]+1); 664 break; 665 case 41: 666 for (j=0; j<Arc41cnt; j++) 667 memset((data+byteX+(Arc41y[j]*bytesPerRow)+(Arc41x[j])), col, Arc41rowcnt[j]+1); 668 break; 669 case 42: 670 for (j=0; j<Arc42cnt; j++) 671 memset((data+byteX+(Arc42y[j]*bytesPerRow)+(Arc42x[j])), col, Arc42rowcnt[j]+1); 672 break; 673 case 43: 674 for (j=0; j<Arc43cnt; j++) 675 memset((data+byteX+(Arc43y[j]*bytesPerRow)+(Arc43x[j])), col, Arc43rowcnt[j]+1); 676 break; 677 case 44: 678 for (j=0; j<Arc44cnt; j++) 679 memset((data+byteX+(Arc44y[j]*bytesPerRow)+(Arc44x[j])), col, Arc44rowcnt[j]+1); 680 break; 681 case 45: 682 for (j=0; j<Arc45cnt; j++) 683 memset((data+byteX+(Arc45y[j]*bytesPerRow)+(Arc45x[j])), col, Arc45rowcnt[j]+1); 684 break; 685 case 46: 686 for (j=0; j<Arc46cnt; j++) 687 memset((data+byteX+(Arc46y[j]*bytesPerRow)+(Arc46x[j])), col, Arc46rowcnt[j]+1); 688 break; 689 default: // calculate with a loop 690 printf("arcs greater 46 not yet implemented :-)"); 691 } 692} 693 694#define NoEdgeGradients(grad, grad0) \ 695( ((Diff(grad.y, 0)<TOLERANCE || Diff(grad0.y, 0)<TOLERANCE) && Diff(grad.y/grad.x, grad0.y/grad0.x) < 1.5 && \ 696 ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0))) || \ 697 ((Diff(grad.x, 0)<TOLERANCE || Diff(grad0.x, 0)<TOLERANCE) && Diff(grad.x/grad.y, grad0.x/grad0.y) < 1.5 && \ 698 ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0))) || \ 699 (Abs(grad.x) < Abs(grad.y) && grad.y != 0 && grad0.y != 0 && ((grad.y<0 && grad0.y<0) || (grad.y>0 && grad0.y>0)) &&\ 700 Diff(grad.x, 0)>TOLERANCE && Diff(grad0.x, 0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 1.5) || \ 701 (Abs(grad.x) > Abs(grad.y) && grad.x != 0 && grad0.x != 0 && ((grad.x<0 && grad0.x<0) || (grad.x>0 && grad0.x>0)) &&\ 702 Diff(grad.y, 0)>TOLERANCE && Diff(grad0.y, 0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 1.5) || \ 703 (Diff(grad.x, 0.0)>TOLERANCE && Diff(grad0.x, 0.0)>TOLERANCE && Diff(grad.x/grad.y, grad0.x/grad0.y) < 1.5 && \ 704 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 705 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) || \ 706 (Diff(grad.y, 0.0)>TOLERANCE && Diff(grad0.y, 0.0)>TOLERANCE && Diff(grad.y/grad.x, grad0.y/grad0.x) < 1.5 && \ 707 ((grad.x < 0 && grad0.x < 0) || (grad.x > 0 && grad0.x > 0) || \ 708 (grad.y < 0 && grad0.y < 0) || (grad.y > 0 && grad0.y > 0))) ) 709 710-(BOOL)noEdgeOrGapBetweenLines:(VGraphic*)l1 :(VGraphic*)l2 711{ NSPoint l1s, l1e, l2s, l2e, grad1, grad2; 712 713 [(VLine*)l1 getVertices:&l1s :&l1e]; 714 grad1.x = l1e.x - l1s.x; grad1.y = l1e.y - l1s.y; 715 [(VLine*)l2 getVertices:&l2s :&l2e]; 716 grad2.x = l2e.x - l2s.x; grad2.y = l2e.y - l2s.y; 717 718 if ( SqrDistPoints(l1e, l2s) < 5 && NNSameGradients(grad1, grad2) ) // NoEdgeGradients 719 return YES; 720 return NO; 721} 722 723-(BOOL)noEdgeOrGapBetweenGraphics:(VGraphic*)l1 :(VGraphic*)l2 724{ NSPoint l1s, l1e, l2s, l2e, grad1, grad2, p1, p2, pm; 725 726 if ( [l1 isKindOfClass:[VLine class]] ) 727 { [(VLine*)l1 getVertices:&l1s :&l1e]; 728 grad1.x = l1e.x - l1s.x; grad1.y = l1e.y - l1s.y; 729 } 730 else 731 { [(VCurve*)l1 getVertices:&l1s :&p1 :&p2 :&l1e]; 732 pm = CenterPoint(p1, p2); 733 grad1.x = l1e.x - pm.x; grad1.y = l1e.y - pm.y; 734 } 735 736 if ( [l2 isKindOfClass:[VLine class]] ) 737 { [(VLine*)l2 getVertices:&l2s :&l2e]; 738 grad2.x = l2e.x - l2s.x; grad2.y = l2e.y - l2s.y; 739 } 740 else 741 { [(VCurve*)l2 getVertices:&l2s :&p1 :&p2 :&l2e]; 742 pm = CenterPoint(p1, p2); 743 grad2.x = pm.x - l2s.x; grad2.y = pm.y - l2s.y; 744 } 745 if ( SqrDistPoints(l1e, l2s) < TOLERANCE && SameGradients(grad1, grad2) ) 746 return YES; 747 return NO; 748} 749 750- (void)uniteCurvesToLines:(VPath*)path :(int)w 751{ int i, j, k, lineCnt=0, curveCnt=0; 752 NSPoint ls, le, l1e, l2s, l2e, p1, p2; 753 VGraphic *lineG, *l1, *l2; 754 NSMutableArray *myList; 755 NSColor *nxBlack = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 756 757 myList = [[[NSMutableArray allocWithZone:[self zone]] init] autorelease]; 758 759 if ( ![[path list] count] ) 760 return; 761 762 /* collect curves (NO edge between!!!) and test if they are on a line 763 * remove curves and add line 764 */ 765 for (i=0; i<(int)[[path list] count]; i++) 766 { id g1 = [[path list] objectAtIndex:i], g2; 767 NSPoint s, e; 768 int noEdge = 0, onlyThreeTimes = 0; 769 770 if ( i < (int)[[path list] count]-1 ) 771 { g2 = [[path list] objectAtIndex:i+1]; 772 noEdge = [self noEdgeOrGapBetweenGraphics:g1 :g2]; 773 } 774 else 775 { g2 = [[path list] objectAtIndex:i-1]; 776 noEdge = [self noEdgeOrGapBetweenGraphics:g2 :g1]; 777 if ( !noEdge && lineCnt > 3 ) 778 [myList addObject:[[path list] objectAtIndex:i]]; 779 } 780 if ( noEdge && i < (int)[[path list] count]-1 ) 781 { lineCnt++; 782 continue; 783 } 784 else if ( lineCnt <= 3 ) 785 { for (j=0; j<=lineCnt; j++) 786 [myList addObject:[[path list] objectAtIndex:i-j]]; 787 if ( i == (int)[[path list] count]-2 ) 788 [myList addObject:g2]; 789 lineCnt=0; 790 continue; 791 } 792 /* set lineG */ 793 l1=[[path list] objectAtIndex:i-lineCnt]; 794 l2=[[path list] objectAtIndex:i]; 795 if ( [l1 isKindOfClass:[VLine class]] ) 796 [(VLine*)l1 getVertices:&ls :&l1e]; 797 else 798 [(VCurve*)l1 getVertices:&ls :&p1 :&p2 :&l1e]; 799 800 if ( [l2 isKindOfClass:[VLine class]] ) 801 [(VLine*)l2 getVertices:&l2s :&le]; 802 else 803 [(VCurve*)l2 getVertices:&l2s :&p1 :&p2 :&le]; 804 lineG = [VLine line]; 805 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 806 [(VLine*)lineG setVertices:ls :le]; 807 onlyThreeTimes = 0; 808 809 /* test curves */ 810 for (j=i-lineCnt, k=0; k<lineCnt+1; k++, j++) 811 { VGraphic *lg=[[path list] objectAtIndex:j]; 812 float tol = 9.0; 813 814 if ( [lg isKindOfClass:[VLine class]] ) 815 { [(VLine*)lg getVertices:&s :&e]; 816 if ( (sqrDistancePointLine(&ls, &le, &s) <= tol) && (sqrDistancePointLine(&ls, &le, &e) <= tol) ) 817 curveCnt++; 818 else if ( !curveCnt && onlyThreeTimes < 4 ) 819 { VGraphic *lg=[[path list] objectAtIndex:i-lineCnt]; 820 [myList addObject:lg]; 821 /* correct lineG */ 822 lg = [[path list] objectAtIndex:i-lineCnt+1]; 823 [(VLine*)lg getVertices:&l2s :&l2e]; 824 [(VLine*)lineG setVertices:l2s :le]; 825 lineCnt --; k = -1; 826 onlyThreeTimes++; 827 } 828 else 829 break; 830 } 831 else 832 { [(VCurve*)lg getVertices:&s :&p1 :&p2 :&e]; 833 if ( (sqrDistancePointLine(&ls, &le, &s) <= tol) && (sqrDistancePointLine(&ls, &le, &e) <= tol) 834 && (sqrDistancePointLine(&ls, &le, &p1) <= tol) && (sqrDistancePointLine(&ls, &le, &p2) <= tol) ) 835 curveCnt++; 836 else if ( !curveCnt && onlyThreeTimes < 4 ) 837 { VGraphic *lg=[[path list] objectAtIndex:i-lineCnt]; 838 [myList addObject:lg]; 839 /* correct lineG */ 840 lg = [[path list] objectAtIndex:i-lineCnt+1]; 841 [(VCurve*)lg getVertices:&l2s :&p1 :&p2 :&l2e]; 842 [(VLine*)lineG setVertices:l2s :le]; 843 lineCnt --; k = -1; 844 onlyThreeTimes++; 845 } 846 else 847 break; 848 } 849 } 850 /* build line from curves (curveCnt) */ 851 if ( curveCnt > 1 ) 852 { 853 if ( curveCnt < lineCnt ) 854 { 855 g2=[[path list] objectAtIndex:i-lineCnt+curveCnt]; 856 if ( [g2 isKindOfClass:[VLine class]] ) 857 [(VLine*)g2 getVertices:&l2s :&l2e]; 858 else 859 [(VCurve*)g2 getVertices:&l2s :&p1 :&p2 :&l2e]; 860 [(VLine*)lineG setVertices:ls :l2e]; 861 } 862 [myList addObject:lineG]; 863 864 if ( curveCnt < lineCnt ) 865 { for (j=i-lineCnt+curveCnt+1, k=curveCnt; k<lineCnt; k++, j++) 866 { VGraphic *lg=[[path list] objectAtIndex:j]; 867 [myList addObject:lg]; 868 } 869 } 870 } 871 else 872 { 873 for (j=i-lineCnt, k=0; k<lineCnt+1; k++, j++) 874 { VGraphic *lg=[[path list] objectAtIndex:j]; 875 [myList addObject:lg]; 876 } 877 } 878 lineCnt=0; 879 curveCnt=0; 880 } 881 /* list to path */ 882 [path setList:myList]; /* optimize list also */ 883} 884 885-(BOOL)noEdgeOrGapBetweenCurves:(VGraphic*)l1 :(VGraphic*)l2 886{ NSPoint l1s, l1e, l2s, l2e, grad1, grad2, p1, p2; 887 888 [(VCurve*)l1 getVertices:&l1s :&p1 :&p2 :&l1e]; 889 grad1.x = l1e.x - p2.x; grad1.y = l1e.y - p2.y; 890 891 [(VCurve*)l2 getVertices:&l2s :&p1 :&p2 :&l2e]; 892 grad2.x = p1.x - l2s.x; grad2.y = p1.y - l2s.y; 893 894 if ( SqrDistPoints(l1e, l2s) < TOLERANCE && SameGradients(grad1, grad2) ) 895 return YES; 896 return NO; 897} 898 899/* never used ? 900 */ 901- (void)unite3CurvesTo1Curve:(VPath*)path 902{ int i, j, k, lineCnt=0; 903 NSMutableArray *myList; 904 905 myList = [[[NSMutableArray allocWithZone:[self zone]] init] autorelease]; 906 907 if ( ![[path list] count] ) 908 return; 909 910 /* collect curves (NO edge between!!!) and test if they are on a line 911 * remove curves and add line 912 */ 913 for (i=0; i<(int)[[path list] count]; i++) 914 { id g1 = [[path list] objectAtIndex:i], g2; 915 int noEdge = 0; 916 917 if ( i < (int)[[path list] count]-1 ) 918 { g2 = [[path list] objectAtIndex:i+1]; 919 if ( [g1 isKindOfClass:[VCurve class]] && [g2 isKindOfClass:[VCurve class]] ) 920 noEdge = [self noEdgeOrGapBetweenCurves:g1 :g2]; 921 else noEdge = 0; 922 } 923 else 924 { g2 = [[path list] objectAtIndex:i-1]; 925 if ( [g1 isKindOfClass:[VCurve class]] && [g2 isKindOfClass:[VCurve class]] ) 926 noEdge = [self noEdgeOrGapBetweenCurves:g2 :g1]; 927 else noEdge = 0; 928 if ( !noEdge && lineCnt > 3 ) 929 [myList addObject:[[path list] objectAtIndex:i]]; 930 } 931 if ( noEdge && i < (int)[[path list] count]-1 ) 932 { lineCnt++; 933 continue; 934 } 935 else if ( lineCnt <= 3 ) 936 { for (j=0; j<=lineCnt; j++) 937 [myList addObject:[[path list] objectAtIndex:i-j]]; 938 if ( i == (int)[[path list] count]-2 ) 939 [myList addObject:g2]; 940 lineCnt=0; 941 continue; 942 } 943 /* set lineG */ 944 945 /* unite curves - allways three */ 946// for (j=i-lineCnt, k=0; k<lineCnt+1; k+=3, j++) 947 for (j=i-lineCnt, k=0; k<lineCnt+1-2; k+=3, j+=3) 948 { VGraphic *c1 = [[path list] objectAtIndex:j]; 949 VGraphic *c2 = [[path list] objectAtIndex:j+1]; 950 VGraphic *c3 = [[path list] objectAtIndex:j+2]; 951 NSPoint s1, c1p1, c1p2, e1, s2, c2p1, c2p2, e2, s3, c3p1, c3p2, e3; 952 953 [(VCurve*)c1 getVertices:&s1 :&c1p1 :&c1p2 :&e1]; 954 [(VCurve*)c2 getVertices:&s2 :&c2p1 :&c2p2 :&e2]; 955 [(VCurve*)c3 getVertices:&s3 :&c3p1 :&c3p2 :&e3]; 956 [(VCurve*)c1 calcVerticesFromPoints:s1 :e1 :e2 :e3]; 957 [myList addObject:c1]; 958 } 959 for ( ; k<lineCnt+1; k++, j++ ) // FIXME: is it correct to start at j ? 960 { VGraphic *lg = [[path list] objectAtIndex:j]; 961 [myList addObject:lg]; 962 } 963 lineCnt = 0; 964 } 965 /* list to path */ 966 [path setList:myList]; /* optimize list also */ 967} 968 969- (void)uniteLinesWithSameGradient2:(VPath*)path :(int)w 970{ int i, j, k, lineCnt=0; 971 NSPoint s1, e1, s2, e2, grad1, grad2; 972 973 if ( ![[path list] count] ) 974 return; 975 976 // unite realy vertical lines ! 977 for (i=0; i<(int)[[path list] count]-1; i++) 978 { VGraphic *l1=[[path list] objectAtIndex:i]; 979 VGraphic *l2=[[path list] objectAtIndex:i+1]; 980 981 [(VLine*)l1 getVertices:&s1 :&e1]; 982 [(VLine*)l2 getVertices:&s2 :&e2]; 983 if ( e1.x == s1.x && e2.x == s2.x && e1.x == s2.x && e1.y == s2.y ) 984 { 985 [(VLine*)l1 setVertices:s1 :e2]; /* l1 go now until l2 end */ 986 [[path list] removeObjectAtIndex:i+1]; /*[l2 release];*/ 987 i--; 988 } 989 } 990 991 for (i=0; i<(int)[[path list] count]; i++) 992 { id g1 = [[path list] objectAtIndex:i], g2; 993 int noEdge = 0; 994 995 if ( i < (int)[[path list] count]-1 ) 996 { g2 = [[path list] objectAtIndex:i+1]; 997 [(VLine*)g1 getVertices:&s1 :&e1]; 998 grad1.x = e1.x - s1.x; grad1.y = e1.y - s1.y; 999 [(VLine*)g2 getVertices:&s2 :&e2]; 1000 grad2.x = e2.x - s2.x; grad2.y = e2.y - s2.y; 1001 if ( [self noEdgeOrGapBetweenLines:g1 :g2] && NearlySameGradients(grad1, grad2) ) 1002 noEdge = 1.0; 1003 else 1004 noEdge = 0.0; 1005 } 1006 else 1007 { g2 = [[path list] objectAtIndex:i-1]; 1008 [(VLine*)g1 getVertices:&s1 :&e1]; 1009 grad1.x = e1.x - s1.x; grad1.y = e1.y - s1.y; 1010 [(VLine*)g2 getVertices:&s2 :&e2]; 1011 grad2.x = e2.x - s2.x; grad2.y = e2.y - s2.y; 1012 if ( [self noEdgeOrGapBetweenLines:g2 :g1] && NearlySameGradients(grad1, grad2) ) 1013 noEdge = 1.0; 1014 else 1015 noEdge = 0.0; 1016 } 1017 if ( noEdge && i < (int)[[path list] count]-1 ) 1018 { lineCnt++; 1019 continue; 1020 } 1021 else if ( lineCnt <= 3 ) 1022 { lineCnt=0; 1023 continue; 1024 } 1025 /* unite lines - allways two */ 1026 for (j=i-lineCnt, k=0; k<lineCnt+1-1 && lineCnt > 3; k+=2, j++) 1027 { VGraphic *l1=[[path list] objectAtIndex:j]; 1028 VGraphic *l2=[[path list] objectAtIndex:j+1]; 1029 1030 [(VLine*)l1 getVertices:&s1 :&e1]; 1031 [(VLine*)l2 getVertices:&s2 :&e2]; 1032 [(VLine*)l1 setVertices:s1 :e2]; /* l1 go now until l2 end */ 1033 [[path list] removeObjectAtIndex:j+1]; 1034 i--; 1035 } 1036 lineCnt = 0; 1037 } 1038} 1039 1040/* build from n f[] values (t[] are the distance between f[] values) 1041 * splineSize calcf[] interpolated values (x or y) 1042 */ 1043void cubicSplineC(int n, double t[], double f[], int splineSize, double calcf[]) 1044{ int i,j; 1045 double a[n], b[n], c[n], delta_t[n], D[n], m[n], k[n]; 1046 double bh, dh, e, h, wt, dt; 1047 1048 for (i=1; i<n; i++) 1049 { 1050 delta_t[i] = t[i]-t[i-1]; 1051 D[i] = (f[i]-f[i-1])/delta_t[i]; 1052 } 1053 m[0] = delta_t[2]; 1054 delta_t[0] = t[2]-t[0]; 1055 h = delta_t[1]; 1056 k[0] = ((h + 2*delta_t[0])*D[1]*delta_t[2]+h*h*D[2])/delta_t[0]; 1057 for (i=1; i<(n-1); i++) 1058 { 1059 h = -delta_t[i+1]/m[i-1]; 1060 k[i] = h*k[i-1]+3*(delta_t[i]*D[i+1]+delta_t[i+1]*D[i]); 1061 m[i] = h *delta_t[i-1] + 2* (delta_t[i] + delta_t[i+1]); 1062 } 1063 h = t[n-1]-t[n-3]; 1064 dh = delta_t[n-1]; 1065 k[n-1] = ((dh+h+h)*D[n-1]*delta_t[n-2] + dh*dh*D[n-2])/h; 1066 h = -h/m[n-2]; 1067 m[n-1] = delta_t[n-2]; 1068 m[n-1] = h*delta_t[n-2] + m[n-1]; 1069 a[n-1] = (h*k[n-2]+k[n-1])/m[n-1]; 1070 for (i=n-2; i>=0; i--) 1071 a[i] = (k[i]-delta_t[i]*a[i+1])/m[i]; 1072 for (i=1; i<n; i++) 1073 { 1074 dh = D[i]; bh = delta_t[i]; 1075 e = a[i-1]+a[i]-dh-dh; 1076 b[i-1] = 2*(dh-a[i-1]-e)/bh; 1077 c[i-1] = 6*e/(bh*bh); 1078 } 1079 wt = 0; j=0; 1080 dt = t[n-1]/(double)(splineSize-1); 1081 for (i=0; i<splineSize; i++) 1082 { 1083 while ( (t[j+1]<wt) && (j<splineSize) ) 1084 j++; 1085 h = wt - t[j]; 1086 calcf[i] = f[j]+h*(a[j]+h*(b[j]+h*c[j]/3)/2); 1087 wt = wt+dt; 1088 } 1089 calcf[splineSize-1] = f[n-1]; 1090} 1091 1092-(void)addCurvesFromBSplineToList:(NSMutableArray*)listle :(int)cnt :(NSPoint*)bSplinePts 1093{ NSPoint b[3*cnt+1]; 1094 long m, k; 1095 NSColor *nxBlack=[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 1096 1097 m = cnt; // m = Anzahl der Gewichtspunkte der BSpline 1098 m--; // m Gewichtspunkte ergeben m-1 Polynome oder Kurvenzuege bzw Bezier-Kurven 1099 1100 b[0] = bSplinePts[0]; 1101 b[3*m] = bSplinePts[m]; 1102 // Bezierpunkte b[i] aus Gewichtspunkten berechnen 1103 for (k=1; k<=m; k++) /* calc all p1 of curves */ 1104 { 1105 b[3*k-2].x = (2.0*bSplinePts[k-1].x + bSplinePts[k].x) / 3.0; 1106 b[3*k-2].y = (2.0*bSplinePts[k-1].y + bSplinePts[k].y) / 3.0; 1107 } 1108 for (k=1; k<=m-1; k++) /* calc p3 of curves */ 1109 { 1110 b[3*k].x = (bSplinePts[k-1].x + 4.0*bSplinePts[k].x + bSplinePts[k+1].x) / 6.0; 1111 b[3*k].y = (bSplinePts[k-1].y + 4.0*bSplinePts[k].y + bSplinePts[k+1].y) / 6.0; 1112 } 1113 for (k=0; k<=m-1; k++) /* calc all p2 of curves */ 1114 { 1115 b[3*k+2].x = (bSplinePts[k].x + 2.0*bSplinePts[k+1].x) / 3.0; 1116 b[3*k+2].y = (bSplinePts[k].y + 2.0*bSplinePts[k+1].y) / 3.0; 1117 } 1118 // jeweils Endpunkt der letzten VCurve als Anfangspunkt in die naechste Kurve uebernehmen! 1119 for (k=3; k<=3*m; k+=3) 1120 { VGraphic *curveG = [VCurve curve]; 1121 1122 [curveG setColor:nxBlack]; 1123 [curveG setWidth:0]; 1124 [(VCurve*)curveG setVertices:b[k-3] :b[k-2] :b[k-1] :b[k]]; /* p0 p1 p2 p3 */ 1125 [listle addObject:curveG]; 1126 } 1127} 1128 1129- (void)linesToCurvesInPath:(VPath*)path :(int)w 1130{ int i, j, k, lineCnt=0; 1131 NSPoint ls, le; 1132 NSMutableArray *myList; 1133 1134 if ( [[path list] count] < 2 ) 1135 return; 1136 1137 myList = [[[NSMutableArray allocWithZone:[self zone]] init] autorelease]; 1138 1139 /* unite lines with same gradients */ 1140 [self uniteLinesWithSameGradient2:path :w]; 1141//return; 1142 1143 if ( [[path list] count] < 2 ) 1144 return; 1145 1146 /* build bSplines from lines and than curves from bSplines */ 1147 1148 /* collect 3/4 lines (NO edge between!!!) and make a bSpline->curve from it 1149 * remove lines and add curves 1150 */ 1151 for (i=0; i<(int)[[path list] count]; i++) 1152 { id g1 = [[path list] objectAtIndex:i], g2; 1153 int noEdge = 0, sameLength = 0, len1, len2, addLastGraphic=0; 1154 NSPoint s1, e1, s2, e2; 1155 1156 if ( i < (int)[[path list] count]-1 ) 1157 { g2 = [[path list] objectAtIndex:i+1]; 1158 noEdge = [self noEdgeOrGapBetweenLines:g1 :g2]; 1159 [(VLine*)g1 getVertices:&s1 :&e1]; 1160 [(VLine*)g2 getVertices:&s2 :&e2]; 1161 len1 = SqrDistPoints(s1, e1); 1162 len2 = SqrDistPoints(s2, e2); 1163 ( Diff(len1, len2) <= 25 ) ? (sameLength = 1) : (sameLength = 0); 1164 } 1165 else 1166 { g2 = [[path list] objectAtIndex:i-1]; 1167 noEdge = [self noEdgeOrGapBetweenLines:g2 :g1]; 1168 [(VLine*)g1 getVertices:&s1 :&e1]; 1169 [(VLine*)g2 getVertices:&s2 :&e2]; 1170 ( Diff(SqrDistPoints(s1, e1), SqrDistPoints(s2, e2)) <= 25 ) ? (sameLength = 1) : (sameLength = 0); 1171 if ( (!noEdge || !sameLength) && lineCnt >= 3 ) 1172 { addLastGraphic = 1; i--; } // lineCnt from previous i !!!! 1173// [myList addObject:[[path list] objectAtIndex:i]]; 1174 } 1175 if ( noEdge && sameLength && i < (int)[[path list] count]-1 ) // sameLength !!! 1176 { lineCnt++; 1177 continue; 1178 } 1179 else if ( lineCnt < 3 ) 1180// for (j=0; j<=lineCnt; j++) 1181 { for (j=lineCnt; j>=0; j--) // hold sort of list !!! 1182 [myList addObject:[[path list] objectAtIndex:i-j]]; 1183 if ( i == (int)[[path list] count]-2 ) 1184 { [myList addObject:g2]; 1185 break; // ende !!! 1186 } 1187 lineCnt=0; 1188 continue; 1189 } 1190 1191 /* if ( lineCnt > 3 ) */ 1192 { double x[lineCnt+2], y[lineCnt+2], t[lineCnt+2]; /* x,y coordinates our linePts and t */ 1193 double ax, ay, dd; 1194 int splineSize = (lineCnt+1.0 > 3) ? (lineCnt+1.0) : (4); 1195// int splineSize = (Even((lineCnt+1))) ? (lineCnt+2.0) : (lineCnt+1.0); 1196 NSPoint bSplinePts[splineSize+1]; 1197 double calcfx[splineSize+1], calcfy[splineSize+1]; 1198 1199 /* build spline through points */ 1200//printf("\n%i", lineCnt); 1201 /* fill x,y value Arrays and calc t values - lineCnt+1 lines -> lineCnt + 2 pts 1202 * with dist = 1/3*(dx+dy+2*max{dx,dy}) (euclid) */ 1203 for (j=i-lineCnt, k=0; k<lineCnt+1; k++, j++) 1204 { VGraphic *lg=[[path list] objectAtIndex:j]; 1205 1206 [(VLine*)lg getVertices:&ls :&le]; 1207 x[k] = ls.x; 1208 y[k] = ls.y; 1209//printf("linePts:\t%.2f x\t%.2f y\n", ls.x, ls.y); 1210 if ( k == lineCnt ) /* last line we need also the end */ 1211 { x[k+1] = le.x; 1212 y[k+1] = le.y; 1213//printf("linePts:\t%.2f x\t%.2f y\n", le.x, le.y); 1214 break; 1215 } 1216 } 1217//printf("\n\n"); 1218 1219 t[0] = 0.0; 1220 for (j=1; j<lineCnt+2; j++) /* we have lineCnt+1 lines -> lineCnt+2 t values to points */ 1221 { ax = Abs(x[j]-x[j-1]); 1222 ay = Abs(y[j]-y[j-1]); 1223 dd = ax + ay; 1224 if ( ax > ay ) dd = dd + 2.0*ax; 1225 else dd = dd + 2.0*ay; 1226 t[j] = t[j-1] + dd/3.0; 1227 } 1228 /* calc interpolation values*/ 1229 cubicSplineC(lineCnt+2, t, x, splineSize, calcfx); 1230 cubicSplineC(lineCnt+2, t, y, splineSize, calcfy); 1231 for (j=0; j<splineSize; j++) 1232 { bSplinePts[j].x = calcfx[j]; 1233 bSplinePts[j].y = calcfy[j]; 1234//printf("splinePts:\t%.2f x\t%.2f y\n", bSplinePts[j].x, bSplinePts[j].y); 1235if ( calcfx[j] < 0 || calcfy[j] < 0 ) 1236 printf("oh no 2\n"); 1237 } 1238//printf("\n"); 1239 /* build curves from bSpline */ 1240 [self addCurvesFromBSplineToList:myList :splineSize :bSplinePts]; 1241 if ( addLastGraphic ) 1242 { [myList addObject:[[path list] objectAtIndex:(int)[[path list] count]-1]]; // to hold sort of list 1243 i++; // correct i ! 1244 } 1245 lineCnt = 0; 1246 } 1247 } 1248 /* list to path */ 1249 [path setList:myList]; /* optimize list also */ 1250} 1251 1252 1253 1254- (float)distanceParallelLines:(VLine*)l1 :(VLine*)l2 :(int)fillDist 1255{ NSPoint l1S, l1E, l2S, l2E; 1256 float xDistS, xDistE, yDist, dist, d1, d2; 1257 1258 [l1 getVertices:&l1S :&l1E]; 1259 [l2 getVertices:&l2S :&l2E]; 1260 1261 xDistS = Diff(l1E.x, l2S.x); 1262 xDistE = Diff(l1E.x, l2E.x); 1263 yDist = Diff(l1E.y, l2S.y); 1264 1265 if ( Diff(yDist, fillDist) < TOLERANCE && (xDistS < 5 || xDistE < 5) ) 1266 { 1267 if ( xDistE < 5 ) 1268 [l2 setVertices:l2E :l2S]; /* change direction */ 1269 dist = 0; 1270 } 1271 else 1272 { if ( (d1=SqrDistPoints(l1E, l2S)) < (d2=SqrDistPoints(l1E, l2E)) ) 1273 dist = d1; 1274 else 1275 { [l2 setVertices:l2E :l2S]; /* change direction */ 1276 dist = d2; 1277 } 1278 } 1279 return dist; 1280} 1281#if 0 1282- (void)uniteLinesWithSameGradient:(VPath*)path :(int)w 1283{ int i, j, k, m, uniteUntil = 0; 1284 NSPoint l1S, l1E, l2S, l2E, l3S, l3E, mPts[1000], tp; // FIX ME - malloc points 1285 float maxDiff = 0.25, sqrDist = 10, maxLen = (w+1)*(w+1); // maxDiff was 0.35 mit mPts; 1286 1287 if ( ![[path list] count] ) 1288 return; 1289//return; 1290 /* unite short lines all other */ 1291 for (i=0; i<(int)[[path list] count]-1; i++) 1292 { VGraphic *l1=[[path list] objectAtIndex:i]; 1293 VGraphic *l2=[[path list] objectAtIndex:i+1]; 1294 NSPoint lastEndPt; 1295 float d1, d2, d3, dl1, dl2, dl3, angleDiff = 15, angle1, angle2, lastAngle=0; 1296 int mCnt = 0; 1297 BOOL curveAhead = NO; 1298 1299 [(VLine*)l1 getVertices:&l1S :&l1E]; 1300 [(VLine*)l2 getVertices:&l2S :&l2E]; 1301// mPts[mCnt++] = CenterPoint(l1S, l1E); 1302 mPts[mCnt++] = l1E; 1303// mPts[mCnt++] = CenterPoint(l2S, l2E); 1304 mPts[mCnt++] = l2S; 1305 dl1 = SqrDistPoints(l1S, l1E); 1306 dl2 = SqrDistPoints(l2S, l2E); 1307 sqrDist = SqrDistPoints(l1E, l2S); 1308 lastEndPt = l2E; 1309 1310if (mCnt > 999) 1311 NSLog(@"PathContour.m: -uniteLinesWith... mPts Ueberlauf"); 1312 1313 if ( sqrDist > 5 || (l1S.y == l1E.y && Diff(l1S.x, l1E.x) > w*2.0) || /*dl1 > maxLen ||*/ 1314 (d1 = pointOnLineClosestToPoint(l1S, l2E, mPts[mCnt-1], &tp)) > maxDiff ) 1315 continue; 1316 if ( /*dl2 > maxLen ||*/ (l2S.y == l2E.y && Diff(l2S.x, l2E.x) > w*2.0) || 1317 (d2 = pointOnLineClosestToPoint(l1S, l2E, mPts[mCnt-1], &tp)) > maxDiff ) 1318 continue; 1319 1320 angle1 = [(VLine*)l1 angle]; 1321 lastAngle = angle2 = [(VLine*)l2 angle]; 1322 if ( Diff(angle1, angle2) > angleDiff && Diff(Diff(angle1, angle2), 360.0) > angleDiff ) 1323 continue; 1324 1325 for (j=i+2 ;j<(int)[[path list] count]; j++) 1326 { VGraphic *l3=[[path list] objectAtIndex:j]; 1327 float angle3; 1328 1329 [(VLine*)l3 getVertices:&l3S :&l3E]; 1330// mPts[mCnt++] = CenterPoint(l3S, l3E); 1331 mPts[mCnt++] = l3S; 1332 1333 dl3 = SqrDistPoints(l3S, l3E); 1334 sqrDist = SqrDistPoints(lastEndPt, l3S); 1335 lastEndPt = l3E; 1336 1337 angle3 = [(VLine*)l3 angle]; 1338 if ( (Diff(lastAngle, angle3) > angleDiff && Diff(Diff(lastAngle, angle3), 360.0) > angleDiff) || 1339 (l3S.y == l3E.y && Diff(l3S.x, l3E.x) > w*2.0) ) 1340 { curveAhead = YES; 1341 uniteUntil = j - 1; 1342 break; 1343 } 1344 lastAngle = angle3; 1345 1346 /* check all mPts start at end */ 1347 for (m=mCnt-1; m >= 0; m--) 1348 { 1349 if ( (Diff(lastAngle, angle3) > angleDiff && Diff(Diff(lastAngle, angle3), 360.0) > angleDiff) || 1350 /*dl3 > maxLen ||*/ sqrDist > 5 || 1351 (d3 = pointOnLineClosestToPoint(l1S, l3E, mPts[m], &tp)) > maxDiff ) 1352 { 1353 curveAhead = YES; 1354 uniteUntil = j - 1; // j - (mCnt - ((!m) ? (1):(m))); 1355 break; 1356 } 1357 } 1358 if ( curveAhead ) 1359 { 1360 break; 1361 } 1362 } 1363 1364 if ( !curveAhead ) 1365 uniteUntil = [[path list] count]-1; 1366 /* unite lines until j-(mCnt-m) ????????? */ 1367 if ( Diff(uniteUntil, i) >= 1 ) 1368 { VGraphic *uline=[[path list] objectAtIndex:uniteUntil]; 1369 1370 [(VLine*)uline getVertices:&l3S :&l3E]; 1371 [(VLine*)l1 setVertices:l1S :l3E]; 1372 for (k=uniteUntil; k > i; k--) 1373 { 1374 if ( k < [[path list] count] ) 1375 [[path list] removeObjectAtIndex:k]; 1376 else 1377 NSLog(@"falscher index"); 1378 } 1379 } 1380 } 1381} 1382#endif 1383#if 0 1384- (void)uniteLinesWithSameGradient:(VPath*)path :(int)w 1385{ int i, j, k, curveI=-1; 1386 NSPoint l1S, l1E, l2S, l2E, l3S, l3E, l4S, l4E; 1387 float angleDiff = 6.0, angleD1 = 0.01, angleD2 = 0.02; 1388 BOOL curveAhead = NO; 1389 1390 if ( ![[path list] count] ) 1391 return; 1392 1393 for (i=0; i<(int)[[path list] count]-1; i++) 1394 { VGraphic *l1=[[path list] objectAtIndex:i]; 1395 VGraphic *l2=[[path list] objectAtIndex:i+1]; 1396 float angle1, angle2, aVals[10]; 1397 int aCnt = 0; 1398 1399 [(VLine*)l1 getVertices:&l1S :&l1E]; 1400 [(VLine*)l2 getVertices:&l2S :&l2E]; 1401 angle1 = [(VLine*)l1 angle]; 1402 angle2 = [(VLine*)l2 angle]; 1403 aVals[aCnt++] = angle1; 1404 1405 if ( curveAhead == YES && i <= curveI && l1E.x == l2S.x && l1E.y == l2S.y && 1406 (Diff(angle1, angle2) < angleD1 || Diff(Diff(angle1, angle2), 360.0) < angleD1) ) 1407 { 1408 [(VLine*)l1 setVertices:l1S :l2E]; /* l1 go now until l2 end */ 1409 [[path list] removeObjectAtIndex:i+1]; 1410 i--; 1411 continue; 1412 } 1413 else if ( curveAhead == YES && i <= curveI ) 1414 continue; 1415 else if ( curveAhead == YES ) 1416 { curveAhead = NO; 1417 curveI = -1; 1418 } 1419 1420 if ( Diff(angle1, angle2) > angleD2 && Diff(Diff(angle1, angle2), 360.0) > angleD2 ) 1421 aVals[aCnt++] = angle2; 1422 if ( l1E.x == l2S.x && l1E.y == l2S.y && 1423 (Diff(angle1, angle2) < angleDiff || Diff(Diff(angle1, angle2), 360.0) < angleDiff) ) 1424 { 1425 for (j=i+1 ;j<(int)[[path list] count]-1; j++) 1426 { VGraphic *l3=[[path list] objectAtIndex:j]; 1427 VGraphic *l4=[[path list] objectAtIndex:j+1]; 1428 float angle3, angle4; 1429 1430 [(VLine*)l3 getVertices:&l3S :&l3E]; 1431 [(VLine*)l4 getVertices:&l4S :&l4E]; 1432 angle3 = [(VLine*)l3 angle]; 1433 angle4 = [(VLine*)l4 angle]; 1434 if ( l3E.x == l4S.x && l3E.y == l4S.y && 1435 (Diff(angle3, angle4) < angleDiff || Diff(Diff(angle3, angle4), 360.0) < angleDiff) ) 1436 { 1437 if ( Diff(aVals[0], angle4) > angleD2 && Diff(Diff(aVals[0], angle4), 360.0) > angleD2 ) 1438 { 1439 /* new different Angle */ 1440 if ( aCnt > 1 && 1441 Diff(aVals[1], angle4) > angleD2 && Diff(Diff(aVals[1], angle4), 360.0) > angleD2 ) 1442 { 1443// if ( aCnt > 2 && 1444// ((Diff(aVals[2], angle4) > angleD2 && 1445// Diff(Diff(aVals[2], angle4), 360.0) > angleD2) || 1446// ( Diff(j, i) < 9 )) ) 1447 { 1448 /* aCnt ist 3 ist maximum - bis hier uniten */ 1449 if ( Diff(j, i) >= 9 ) 1450 { 1451 [(VLine*)l1 setVertices:l1S :l3E]; 1452 for (k=j; k > i; k--) 1453 [[path list] removeObjectAtIndex:k]; 1454 1455 aCnt = 10.0; // so we do not unite until end 1456 break; 1457 } 1458 /* 4. different Value OR 3 inside 8 lines - curve ahead - no line */ 1459 curveAhead = YES; 1460 curveI = j; 1461 break; 1462 } 1463/* else if ( aCnt == 2 ) 1464 { aVals[aCnt++] = angle4; 1465 continue; 1466 } 1467 else 1468 continue; 1469*/ 1470 } 1471 else if ( aCnt == 1 ) 1472 { aVals[aCnt++] = angle4; 1473 continue; 1474 } 1475 else 1476 continue; 1477 } 1478 else 1479 continue; 1480 } 1481 /* unite all lines until j, if less / or 3 values */ 1482 else if ( (aCnt < 3 && Diff(j, i) > 6) || (aCnt < 4 && Diff(j, i) >= 9) ) 1483 { VLine *lj = [[path list] objectAtIndex:j]; 1484 NSPoint lje = [lj pointWithNum:MAXINT]; 1485 1486 [(VLine*)l1 setVertices:l1S :lje]; 1487 for (k=j; k > i; k--) 1488 [[path list] removeObjectAtIndex:k]; 1489 1490 aCnt = 10.0; // so we do not unite until end 1491 break; 1492 } 1493 else /* else unite only with an angleDiff of angleD1 */ 1494 { 1495 /* 4. different Value OR 3 inside 8 lines - curve ahead - no line */ 1496 curveAhead = YES; 1497 curveI = j; 1498 break; 1499 } 1500 } 1501 /* unite all lines until list end, if less / or 3 values */ 1502 if ( curveAhead == NO && 1503 ((aCnt < 3 && Diff([[path list] count], i) > 6) || 1504 (aCnt < 4 && Diff([[path list] count], i) >= 9)) ) 1505 { VLine *ll = [[path list] objectAtIndex:[[path list] count]-1]; 1506 NSPoint lle = [ll pointWithNum:MAXINT]; 1507 1508 [(VLine*)l1 setVertices:l1S :lle]; 1509 for (j=[[path list] count]-1; j > i; j--) 1510 [[path list] removeObjectAtIndex:j]; 1511 1512 return; 1513 } 1514 /* unite l1 and l2 if angle diff smaller angleD1 */ 1515 else if ( curveAhead == YES && 1516 (Diff(angle1, angle2) < angleD1 || Diff(Diff(angle1, angle2), 360.0) < angleD1) ) 1517 { 1518 [(VLine*)l1 setVertices:l1S :l2E]; /* l1 go now until l2 end */ 1519 [[path list] removeObjectAtIndex:i+1]; 1520 i--; 1521 } 1522 } 1523 } 1524} 1525#endif 1526 1527// OLD 1528- (void)uniteLinesWithSameGradient:(VPath*)path :(int)w 1529{ int i, sqrDist=(w/2.0)*(w/2.0); 1530 NSPoint grad1, grad2; // grad3; 1531 NSPoint l1S, l1E, l2S, l2E; //, l3S, l3E; 1532 1533 if ( ![[path list] count] ) 1534 return; 1535 1536 // unite realy vertical lines ! 1537 for (i=0; i<(int)[[path list] count]-1; i++) 1538 { VGraphic *l1=[[path list] objectAtIndex:i]; 1539 VGraphic *l2=[[path list] objectAtIndex:i+1]; 1540 1541 [(VLine*)l1 getVertices:&l1S :&l1E]; 1542 [(VLine*)l2 getVertices:&l2S :&l2E]; 1543 if ( l1E.x == l1S.x && l2E.x == l2S.x && l1E.x == l2S.x && l1E.y == l2S.y ) 1544 { 1545 [(VLine*)l1 setVertices:l1S :l2E]; /* l1 go now until l2 end */ 1546 [[path list] removeObjectAtIndex:i+1]; /*[l2 release];*/ 1547 i--; 1548 } 1549 } 1550 1551 for (i=0; i<(int)[[path list] count]-1; i++) 1552 { VGraphic *l1=[[path list] objectAtIndex:i]; 1553 VGraphic *l2=[[path list] objectAtIndex:i+1]; 1554 1555 [(VLine*)l1 getVertices:&l1S :&l1E]; 1556 [(VLine*)l2 getVertices:&l2S :&l2E]; 1557 grad1.x = l1E.x - l1S.x; grad1.y = l1E.y - l1S.y; 1558 grad2.x = l2E.x - l2S.x; grad2.y = l2E.y - l2S.y; 1559 if ( l1E.x == l2S.x && l1E.y == l2S.y && SameGradients(grad1, grad2) && SqrDistPoints(l2S, l2E) < sqrDist && SqrDistPoints(l1S, l1E) < sqrDist ) 1560 { 1561 [(VLine*)l1 setVertices:l1S :l2E]; /* l1 go now until l2 end */ 1562 [[path list] removeObjectAtIndex:i+1]; /*[l2 release];*/ 1563 i--; 1564 } 1565 } 1566#if 0 1567 for (i=0; i<(int)[[path list] count]-2; i++) 1568 { VGraphic *l1=[[path list] objectAtIndex:i]; 1569 VGraphic *l2=[[path list] objectAtIndex:i+1]; 1570 VGraphic *l3=[[path list] objectAtIndex:i+2]; 1571 1572 [(VLine*)l1 getVertices:&l1S :&l1E]; 1573 [(VLine*)l2 getVertices:&l2S :&l2E]; 1574 [(VLine*)l3 getVertices:&l3S :&l3E]; 1575 grad1.x = l1E.x - l1S.x; grad1.y = l1E.y - l1S.y; 1576 grad2.x = l2E.x - l2S.x; grad2.y = l2E.y - l2S.y; 1577 grad3.x = l3E.x - l3S.x; grad3.y = l3E.y - l3S.y; 1578 if ( l1E.x == l2S.x && l1E.y == l2S.y && l2E.x == l3S.x && l2E.y == l3S.y && SameGradients(grad1, grad2) && SameGradients(grad2, grad3) && SameGradients(grad1, grad3) && SqrDistPoints(l2S, l2E) < sqrDist && SqrDistPoints(l1S, l1E) < sqrDist 1579 /*&& (SameGradients(grad1, grad2) || SameGradients(grad3, grad2))*/ ) 1580 { 1581 [(VLine*)l1 setVertices:l1S :l3E]; /* l1 go now until l3 end */ 1582 [[path list] removeObjectAtIndex:i+2]; /*[l3 release];*/ 1583 [[path list] removeObjectAtIndex:i+1]; /*[l2 release];*/ 1584 i--; 1585 } 1586 } 1587#endif 1588 return; 1589} 1590 1591#if 0 1592- (void)smoothenLinesInPath:(VPath*)path :(int)w 1593{ int i, j, k, lineCnt=0; 1594 NSPoint s1, e1, s2, e2, mPrev; 1595 float angle1, angle2, angleDiff1 = 13.0, angleDiff2 = 5.0, angleDiffE = 27.0; 1596 float curAngleDiff = angleDiff1, aDiff = 0.0, sqrDist = 0.0, firstA = -1.0; 1597 1598 if ( [[path list] count] < 2 ) 1599 return; 1600 1601 for (i=0; i<(int)[[path list] count]; i++) 1602 { id g1 = [[path list] objectAtIndex:i], g2; 1603 int noEdge = 0; 1604 1605 if ( i < (int)[[path list] count]-1 ) 1606 { g2 = [[path list] objectAtIndex:i+1]; 1607 [(VLine*)g1 getVertices:&s1 :&e1]; 1608 [(VLine*)g2 getVertices:&s2 :&e2]; 1609 angle1 = [(VLine*)g1 angle]; 1610 angle2 = [(VLine*)g2 angle]; 1611 aDiff = Diff(angle1, angle2); 1612 sqrDist = SqrDistPoints(e1, s2); 1613 /* angleDiff < 0-7 */ 1614 if ( (s1.y == e1.y && Diff(s1.x, e1.x) > w) || (s2.y == e2.y && Diff(s2.x, e2.x) > w) ) 1615 { noEdge = 0.0; 1616 curAngleDiff = angleDiffE; 1617 } 1618 else if (sqrDist < 5 && (aDiff < angleDiff1 || Diff(aDiff, 360.0) < angleDiff1)) 1619 { 1620 if (curAngleDiff == angleDiff1 || curAngleDiff == angleDiffE) 1621 { noEdge = 1.0; 1622 curAngleDiff = angleDiff1; 1623 if (!lineCnt) 1624 firstA = angle1; 1625 } 1626 else if (curAngleDiff == angleDiff2 && // angleDiff < 5-7 1627 aDiff > angleDiff2 && Diff(aDiff, 360.0) > angleDiff2) 1628 noEdge = 1.0; 1629 else 1630 { noEdge = 0.0; 1631 curAngleDiff = angleDiff1; 1632 } 1633 } 1634 /* angleDiff < 8-20 */ 1635 else if (sqrDist < 5 && (aDiff < angleDiffE || Diff(aDiff, 360.0) < angleDiffE)) 1636 { 1637 if (curAngleDiff == angleDiff2) 1638 { noEdge = 1.0; 1639 if (!lineCnt) 1640 firstA = angle1; 1641 } 1642 else 1643 { noEdge = 0.0; 1644 curAngleDiff = angleDiff2; 1645 } 1646 } 1647 /* angleDiff > 20 */ 1648 else 1649 { noEdge = 0.0; 1650 curAngleDiff = angleDiffE; 1651 } 1652 } 1653 else 1654 { g2 = [[path list] objectAtIndex:i-1]; 1655 [(VLine*)g1 getVertices:&s1 :&e1]; 1656 [(VLine*)g2 getVertices:&s2 :&e2]; 1657 angle1 = [(VLine*)g1 angle]; 1658 angle2 = [(VLine*)g2 angle]; 1659 aDiff = Diff(angle1, angle2); 1660 sqrDist = SqrDistPoints(e2, s1); 1661 /* angleDiff < 0-7 */ 1662 if ( (s1.y == e1.y && Diff(s1.x, e1.x) > w) || (s2.y == e2.y && Diff(s2.x, e2.x) > w) ) 1663 { noEdge = 0.0; 1664 curAngleDiff = angleDiffE; 1665 } 1666 else if (sqrDist < 5 && (aDiff < angleDiff1 || Diff(aDiff, 360.0) < angleDiff1)) 1667 { 1668 if (curAngleDiff == angleDiff1 || curAngleDiff == angleDiffE) 1669 { noEdge = 1.0; 1670 curAngleDiff = angleDiff1; 1671 if (!lineCnt) 1672 firstA = angle1; 1673 } 1674 else if (curAngleDiff == angleDiff2 && // angleDiff < 5-7 1675 aDiff > angleDiff2 && Diff(aDiff, 360.0) > angleDiff2) 1676 noEdge = 1.0; 1677 else 1678 { noEdge = 0.0; 1679 curAngleDiff = angleDiff1; 1680 } 1681 } 1682 /* angleDiff < 8-20 */ 1683 else if (sqrDist < 5 && (aDiff < angleDiffE || Diff(aDiff, 360.0) < angleDiffE)) 1684 { 1685 if (curAngleDiff == angleDiff2) 1686 noEdge = 1.0; 1687 else 1688 { noEdge = 0.0; 1689 curAngleDiff = angleDiff2; 1690 } 1691 } 1692 /* angleDiff > 20 */ 1693 else 1694 { noEdge = 0.0; 1695 curAngleDiff = angleDiffE; 1696 } 1697 } 1698 if ( noEdge && i < (int)[[path list] count]-1 ) 1699 { lineCnt++; 1700 continue; 1701 } 1702 else if ( lineCnt <= 3 ) /*|| Diff(firstA, angle1) > angleDiff1*/ 1703 { lineCnt=0; 1704 continue; 1705 } 1706 mPrev.x = mPrev.y = -1; 1707 /* smoothen lines - allways ??? */ 1708 for (j=i-lineCnt, k=0; k<lineCnt+1-1 && lineCnt > 3; k+=2, j+=2) 1709 { VGraphic *l1=[[path list] objectAtIndex:j]; 1710 VGraphic *l2=[[path list] objectAtIndex:j+1]; 1711 NSPoint m1, m2; 1712 1713 [(VLine*)l1 getVertices:&s1 :&e1]; 1714 [(VLine*)l2 getVertices:&s2 :&e2]; 1715 m1 = CenterPoint(s1, e1); 1716 m2 = CenterPoint(s2, e2); 1717 if ( mPrev.x == -1 && mPrev.y == -1 ) // first 1718 [(VLine*)l1 setVertices:s1 :m1]; 1719 else 1720 [(VLine*)l1 setVertices:mPrev :m1]; 1721 [(VLine*)l2 setVertices:m1 :m2]; 1722 mPrev = m2; 1723 if ( k >= lineCnt+1-3 ) // last 1724 { VGraphic *lineG=[VLine line]; 1725 NSColor *nxBlack = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 1726 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 1727 1728 if ( j+2 == lineCnt ) 1729 { VGraphic *l3=[[path list] objectAtIndex:j+2]; 1730 NSPoint s3, e3, m3; 1731 1732 [(VLine*)l3 getVertices:&s3 :&e3]; 1733 m3 = CenterPoint(s3, e3); 1734 [(VLine*)l3 setVertices:m2 :m3]; 1735 [(VLine*)lineG setVertices:m3 :e3]; 1736 [[path list] insertObject:lineG atIndex:j+3]; 1737 } 1738 else 1739 { [(VLine*)lineG setVertices:m2 :e2]; 1740 [[path list] insertObject:lineG atIndex:j+2]; 1741 } 1742 i++; 1743 lineCnt++; // one line more !!! 1744 } 1745 } 1746 /* smoothen lines - allways ------------- second time */ 1747 mPrev.x = mPrev.y = -1; 1748 for (j=i-lineCnt, k=0; k<lineCnt+1-1 && lineCnt > 3; k+=2, j+=2) 1749 { VGraphic *l1=[[path list] objectAtIndex:j]; 1750 VGraphic *l2=[[path list] objectAtIndex:j+1]; 1751 NSPoint m1, m2; 1752 1753 [(VLine*)l1 getVertices:&s1 :&e1]; 1754 [(VLine*)l2 getVertices:&s2 :&e2]; 1755 m1 = CenterPoint(s1, e1); 1756 m2 = CenterPoint(s2, e2); 1757 if ( mPrev.x == -1 && mPrev.y == -1 ) // first 1758 [(VLine*)l1 setVertices:s1 :m1]; 1759 else 1760 [(VLine*)l1 setVertices:mPrev :m1]; 1761 [(VLine*)l2 setVertices:m1 :m2]; 1762 mPrev = m2; 1763 if ( k >= lineCnt+1-3 ) // last 1764 { VGraphic *lineG=[VLine line]; 1765 NSColor *nxBlack = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 1766 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 1767 1768 if ( j+2 == lineCnt ) 1769 { VGraphic *l3=[[path list] objectAtIndex:j+2]; 1770 NSPoint s3, e3, m3; 1771 1772 [(VLine*)l3 getVertices:&s3 :&e3]; 1773 m3 = CenterPoint(s3, e3); 1774 [(VLine*)l3 setVertices:m2 :m3]; 1775 [(VLine*)lineG setVertices:m3 :e3]; 1776 [[path list] insertObject:lineG atIndex:j+3]; 1777 } 1778 else 1779 { [(VLine*)lineG setVertices:m2 :e2]; 1780 [[path list] insertObject:lineG atIndex:j+2]; 1781 } 1782 i++; 1783 } 1784 } 1785#if 0 1786 if ( Diff(firstA, angle1) < angleDiff1 ) // line i hope 1787 { 1788 /* smoothen lines ------------- third time */ 1789 mPrev.x = mPrev.y = -1; 1790 for (j=i-lineCnt, k=0; k<lineCnt+1-1 && lineCnt > 3; k+=2, j+=2) 1791 { VGraphic *l1=[[path list] objectAtIndex:j]; 1792 VGraphic *l2=[[path list] objectAtIndex:j+1]; 1793 NSPoint m1, m2; 1794 1795 [(VLine*)l1 getVertices:&s1 :&e1]; 1796 [(VLine*)l2 getVertices:&s2 :&e2]; 1797 m1 = CenterPoint(s1, e1); 1798 m2 = CenterPoint(s2, e2); 1799 if ( mPrev.x == -1 && mPrev.y == -1 ) // first 1800 [(VLine*)l1 setVertices:s1 :m1]; 1801 else 1802 [(VLine*)l1 setVertices:mPrev :m1]; 1803 [(VLine*)l2 setVertices:m1 :m2]; 1804 mPrev = m2; 1805 if ( k >= lineCnt+1-3 ) // last 1806 { VGraphic *lineG=[VLine line]; 1807 NSColor *nxBlack = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 1808 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 1809 1810 if ( j+2 == lineCnt ) 1811 { VGraphic *l3=[[path list] objectAtIndex:j+2]; 1812 NSPoint s3, e3, m3; 1813 1814 [(VLine*)l3 getVertices:&s3 :&e3]; 1815 m3 = CenterPoint(s3, e3); 1816 [(VLine*)l3 setVertices:m2 :m3]; 1817 [(VLine*)lineG setVertices:m3 :e3]; 1818 [[path list] insertObject:lineG atIndex:j+3]; 1819 } 1820 else 1821 { [(VLine*)lineG setVertices:m2 :e2]; 1822 [[path list] insertObject:lineG atIndex:j+2]; 1823 } 1824 i++; 1825 } 1826 } 1827 } 1828#endif 1829 lineCnt = 0; 1830 } 1831} 1832#endif 1833 1834// OLD 1835- (void)smoothenLinesInPath:(VPath*)path 1836{ int i, j, k, lineCnt=0; 1837 NSPoint s1, e1, s2, e2, grad1, grad2, mPrev; 1838 1839 if ( [[path list] count] < 2 ) 1840 return; 1841 1842 for (i=0; i<(int)[[path list] count]; i++) 1843 { id g1 = [[path list] objectAtIndex:i], g2; 1844 int noEdge = 0; 1845 1846 if ( i < (int)[[path list] count]-1 ) 1847 { g2 = [[path list] objectAtIndex:i+1]; 1848 [(VLine*)g1 getVertices:&s1 :&e1]; 1849 grad1.x = e1.x - s1.x; grad1.y = e1.y - s1.y; 1850 [(VLine*)g2 getVertices:&s2 :&e2]; 1851 grad2.x = e2.x - s2.x; grad2.y = e2.y - s2.y; 1852 if ( SqrDistPoints(e1, s2) < 5 && NNNNSameGradients(grad1, grad2) ) // [self noEdgeOrGapBetweenLines:g1 :g2] 1853 noEdge = 1.0; 1854 else 1855 noEdge = 0.0; 1856 } 1857 else 1858 { g2 = [[path list] objectAtIndex:i-1]; 1859 [(VLine*)g1 getVertices:&s1 :&e1]; 1860 grad1.x = e1.x - s1.x; grad1.y = e1.y - s1.y; 1861 [(VLine*)g2 getVertices:&s2 :&e2]; 1862 grad2.x = e2.x - s2.x; grad2.y = e2.y - s2.y; 1863 if ( SqrDistPoints(e2, s1) < 5 && NNNNSameGradients(grad1, grad2) ) // && [self noEdgeOrGapBetweenLines:g2 :g1] 1864 noEdge = 1.0; 1865 else 1866 noEdge = 0.0; 1867 } 1868 if ( noEdge && i < (int)[[path list] count]-1 ) 1869 { lineCnt++; 1870 continue; 1871 } 1872 else if ( lineCnt <= 3 ) 1873 { lineCnt=0; 1874 continue; 1875 } 1876 mPrev.x = mPrev.y = -1; 1877 /* smoothen lines - allways ??? */ 1878 for (j=i-lineCnt, k=0; k<lineCnt+1-1 && lineCnt > 3; k+=2, j+=2) 1879 { VGraphic *l1=[[path list] objectAtIndex:j]; 1880 VGraphic *l2=[[path list] objectAtIndex:j+1]; 1881 NSPoint m1, m2; 1882 1883 [(VLine*)l1 getVertices:&s1 :&e1]; 1884 [(VLine*)l2 getVertices:&s2 :&e2]; 1885 m1 = CenterPoint(s1, e1); 1886 m2 = CenterPoint(s2, e2); 1887 if ( mPrev.x == -1 && mPrev.y == -1 ) // first 1888 [(VLine*)l1 setVertices:s1 :m1]; 1889 else 1890 [(VLine*)l1 setVertices:mPrev :m1]; 1891 [(VLine*)l2 setVertices:m1 :m2]; 1892 mPrev = m2; 1893 if ( k >= lineCnt+1-3 ) // last 1894 { VGraphic *lineG=[VLine line]; 1895 NSColor *nxBlack = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 1896 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 1897 [(VLine*)lineG setVertices:m2 :e2]; 1898 [[path list] insertObject:lineG atIndex:j+2]; 1899 i++; 1900 } 1901 } 1902 lineCnt = 0; 1903 } 1904} 1905 1906/* modified: 30.01.00 1907 * go on building the path with these new points 1908 */ 1909- (BOOL)pointIsEdge:(NSPoint)pt 1910{ int byteY, byteX; 1911 unsigned char byte, lbyte, rbyte, ubyte, dbyte, ulbyte, urbyte, dlbyte, drbyte; 1912 unsigned char uullbyte, uurrbyte, ddllbyte, ddrrbyte, uulbyte, uurbyte, ddlbyte, ddrbyte; 1913 unsigned char llbyte, rrbyte, uubyte, ddbyte, ullbyte, urrbyte, dllbyte, drrbyte; 1914 unsigned char uuulllbyte, uuullbyte, uuulbyte, uuubyte, uuurbyte, uuurrbyte, uuurrrbyte; 1915 unsigned char uulllbyte, uurrrbyte, ulllbyte, urrrbyte, lllbyte, rrrbyte, dlllbyte, drrrbyte, ddlllbyte; 1916 unsigned char ddrrrbyte, dddlllbyte, dddllbyte, dddlbyte, dddbyte, dddrbyte, dddrrbyte, dddrrrbyte; 1917 1918 byteY = pt.y * bytesPerRow; /* the height */ 1919 byteY = size - byteY - bytesPerRow; 1920 byteX = byteY + pt.x; /* the width in bytes */ 1921 byte = *(data+byteX); 1922 1923// if ( byte != white ) 1924// return NO; 1925 1926 lbyte = *(data+(byteX-1)); rbyte = *(data+(byteX+1)); 1927 dbyte = *(data+byteX+bytesPerRow); ubyte = *(data+byteX-bytesPerRow); 1928 ulbyte = *(data+(byteX-1) - bytesPerRow); urbyte = *(data+(byteX+1) - bytesPerRow); 1929 dlbyte = *(data+(byteX-1) + bytesPerRow); drbyte = *(data+(byteX+1) + bytesPerRow); 1930 1931 uullbyte = *(data+(byteX-2)-(2*bytesPerRow)); uurrbyte = *(data+(byteX+2)-(2*bytesPerRow)); 1932 ddllbyte = *(data+(byteX-2)+(2*bytesPerRow)); ddrrbyte = *(data+(byteX+2)+(2*bytesPerRow)); 1933 uulbyte = *(data+(byteX-1)-(2*bytesPerRow)); uurbyte = *(data+(byteX+1)-(2*bytesPerRow)); 1934 ddlbyte = *(data+(byteX-1)+(2*bytesPerRow)); ddrbyte = *(data+(byteX+1)+(2*bytesPerRow)); 1935 uubyte = *(data+byteX-(2*bytesPerRow)); ddbyte = *(data+byteX+(2*bytesPerRow)); 1936 llbyte = *(data+(byteX-2)); rrbyte = *(data+(byteX+2)); 1937 ullbyte = *(data+(byteX-2) - bytesPerRow); urrbyte = *(data+(byteX+2) - bytesPerRow); 1938 dllbyte = *(data+(byteX-2) + bytesPerRow); drrbyte = *(data+(byteX+2) + bytesPerRow); 1939 1940 uuulllbyte = *(data+(byteX-3)-(3*bytesPerRow)); uuurrrbyte = *(data+(byteX+3)-(3*bytesPerRow)); 1941 uuullbyte = *(data+(byteX-2)-(3*bytesPerRow)); uuurrbyte = *(data+(byteX+2)-(3*bytesPerRow)); 1942 uuulbyte = *(data+(byteX-1)-(3*bytesPerRow)); uuurbyte = *(data+(byteX+1)-(3*bytesPerRow)); 1943 uuubyte = *(data+byteX-(3*bytesPerRow)); dddbyte = *(data+byteX+(3*bytesPerRow)); 1944 lllbyte = *(data+(byteX-3)); rrrbyte = *(data+(byteX+3)); 1945 dddlbyte = *(data+(byteX-1)+(3*bytesPerRow)); dddrbyte = *(data+(byteX+1)+(3*bytesPerRow)); 1946 dddllbyte = *(data+(byteX-2)+(3*bytesPerRow)); dddrrbyte = *(data+(byteX+2)+(3*bytesPerRow)); 1947 dddlllbyte = *(data+(byteX-3)+(3*bytesPerRow)); dddrrrbyte = *(data+(byteX+3)+(3*bytesPerRow)); 1948 ulllbyte = *(data+(byteX-3) - bytesPerRow); urrrbyte = *(data+(byteX+3) - bytesPerRow); 1949 dlllbyte = *(data+(byteX-3) + bytesPerRow); drrrbyte = *(data+(byteX+3) + bytesPerRow); 1950 uulllbyte = *(data+(byteX-3)-(2*bytesPerRow)); uurrrbyte = *(data+(byteX+3)-(2*bytesPerRow)); 1951 ddlllbyte = *(data+(byteX-3)+(2*bytesPerRow)); ddrrrbyte = *(data+(byteX+3)+(2*bytesPerRow)); 1952 1953 if ( !rbyte && !dbyte ) 1954 { 1955 if ( !uuurbyte && !uuurrbyte && !uuurrrbyte && !uurrrbyte && !urrrbyte && !rrrbyte && !drrrbyte && !ddrrrbyte && 1956 !dddrrrbyte && !dddrrbyte && !dddrbyte && !dddbyte && !dddlbyte && !dddllbyte && 1957 !uurbyte && !uurrbyte && !urbyte && !urrbyte && !rrbyte && !drbyte && !drrbyte && !ddrbyte && !ddrrbyte && 1958 !ddbyte && !ddlbyte ) 1959 return YES; 1960 if ( !dlllbyte && !ddlllbyte && !dddlllbyte && !dddllbyte && !dddlbyte && !dddbyte && !dddrbyte && !dddrrbyte && 1961 !dddrrrbyte && !ddrrrbyte && !drrrbyte && !rrrbyte && !urrrbyte && !uurrrbyte && 1962 !urrbyte && !rrbyte && !drbyte && !drrbyte && !ddrbyte && !ddrrbyte && !ddbyte && !ddlbyte && !dlbyte && 1963 !dllbyte && !ddllbyte ) 1964 return YES; 1965 } 1966 if ( !rbyte && !ubyte ) 1967 { 1968 if ( !uuullbyte && !uuulbyte && !uuubyte && !uuurbyte && !uuurrbyte && !uuurrrbyte && !uurrrbyte && !urrrbyte && 1969 !rrrbyte && !drrrbyte && ddrrrbyte && !dddrrrbyte && !dddrrbyte && !dddrbyte && 1970 !uulbyte && !uubyte && !uurbyte && !uurrbyte && !urbyte && !urrbyte && !rrbyte && !drbyte && !drrbyte && 1971 !ddrbyte && !ddrrbyte ) 1972 return YES; 1973 if ( !ulllbyte && !uulllbyte && !uuulllbyte && !uuullbyte && !uuulbyte && !uuubyte && !uuurbyte && !uuurrbyte && 1974 !uuurrrbyte && !uurrrbyte && !urrrbyte && !rrrbyte && !drrrbyte && !ddrrrbyte && 1975 !uullbyte && !ullbyte && !uulbyte && !ulbyte && !uubyte && !uurbyte && !uurrbyte &&!urbyte && !urrbyte && 1976 !rrbyte && !drrbyte ) 1977 return YES; 1978 } 1979 if ( !lbyte && !ubyte ) 1980 { 1981 if ( !urrrbyte && !uurrrbyte && !uuurrrbyte && !uuurrbyte && !uuurbyte && !uuubyte && !uuulbyte && !uuullbyte && 1982 !uuulllbyte && !uulllbyte && !ulllbyte && !lllbyte && !dlllbyte && !ddlllbyte && 1983 !uullbyte && !uulbyte && !uubyte && !uurbyte && !uurrbyte && !urbyte && !urrbyte && !ulbyte && !ullbyte && 1984 !llbyte && !dllbyte ) 1985 return YES; 1986 if ( !uuurrbyte && !uuurbyte && !uuubyte && !uuulbyte && !uuullbyte && !uuulllbyte && !uulllbyte && !ulllbyte && 1987 !lllbyte && !dlllbyte && !ddlllbyte && !dddlllbyte && !dddllbyte && !dddlbyte && 1988 !uullbyte && !uulbyte && !uubyte && !uurbyte && !ulbyte && !ullbyte && !llbyte && !dllbyte && !dlbyte && 1989 !ddllbyte && !ddlbyte ) 1990 return YES; 1991 } 1992 if ( !lbyte && !dbyte ) 1993 { 1994 if ( !uuulbyte && !uuullbyte && !uuulllbyte && !uulllbyte && !ulllbyte && !lllbyte && !dlllbyte && !ddlllbyte && 1995 !dddlllbyte && !dddllbyte && !dddlbyte && !dddbyte && !dddrbyte && !dddrrbyte && 1996 !uullbyte && !uulbyte && !ullbyte && !ulbyte && !llbyte && !dllbyte && !dlbyte && !ddllbyte && !ddlbyte && 1997 !ddrbyte && !ddbyte ) 1998 return YES; 1999 if ( !uulllbyte && !ulllbyte && !lllbyte && !dlllbyte && !ddlllbyte && !dddlllbyte && !dddllbyte && !dddlbyte && 2000 !dddbyte && !dddrbyte && !dddrrbyte && !dddrrrbyte && !ddrrrbyte && !drrrbyte && 2001 !ullbyte && !llbyte && !dllbyte && !dlbyte && !drbyte && !drrbyte && !ddllbyte && !ddlbyte && !ddbyte && 2002 !ddrbyte && !ddrrbyte ) 2003 return YES; 2004 } 2005 // the same++ for white !!! 2006 if ( rbyte==white && dbyte==white && ubyte==white ) 2007 { 2008 if ( white==uubyte && white==uuubyte && white==dlbyte && white==ddllbyte && white==dddlllbyte && 2009 white==uuurbyte && white==uuurrbyte && white==uuurrrbyte && white==uurrrbyte && white==urrrbyte && 2010 white==rrrbyte && white==drrrbyte && white==ddrrrbyte && white==dddrrrbyte && white==dddrrbyte && 2011 white==dddrbyte && white==dddbyte && white==dddlbyte && white==dddllbyte && white==uurbyte && 2012 white==uurrbyte && white==urbyte && white==urrbyte && white==rrbyte && white==drbyte && white==drrbyte && 2013 white==ddrbyte && white==ddrrbyte && white==ddbyte && white==ddlbyte ) 2014 return YES; 2015 if ( white==ddbyte && white==dddbyte && white==uuulllbyte && white==uullbyte && white==ulbyte && 2016 white==uuullbyte && white==uuulbyte && white==uuubyte && white==uuurbyte && white==uuurrbyte && 2017 white==uuurrrbyte && white==uurrrbyte && white==urrrbyte && white==rrrbyte && white==drrrbyte && 2018 ddrrrbyte && white==dddrrrbyte && white==dddrrbyte && white==dddrbyte && white==uulbyte && 2019 white==uubyte && white==uurbyte && white==uurrbyte && white==urbyte && white==urrbyte && white==rrbyte && 2020 white==drbyte && white==drrbyte && white==ddrbyte && white==ddrrbyte ) 2021 return YES; 2022 } 2023 if ( white==rbyte && white==ubyte && white==lbyte ) 2024 { 2025 if ( white==rrbyte && white==rrrbyte && white==dlbyte && ddllbyte && dddlllbyte && 2026 white==urrrbyte && white==uurrrbyte && white==uuurrrbyte && white==uuurrbyte && white==uuurbyte && 2027 white==uuubyte && white==uuulbyte && white==uuullbyte && white==uuulllbyte && white==uulllbyte && 2028 white==ulllbyte && white==lllbyte && white==dlllbyte && white==ddlllbyte && white==uullbyte && 2029 white==uulbyte && white==uubyte && white==uurbyte && white==uurrbyte && white==urbyte && white==urrbyte && 2030 white==ulbyte && white==ullbyte && white==llbyte && white==dllbyte ) 2031 return YES; 2032 if ( white==llbyte && white==lllbyte && white==drbyte && white==ddrrbyte && dddrrrbyte && 2033 white==ulllbyte && white==uulllbyte && white==uuulllbyte && white==uuullbyte && white==uuulbyte && 2034 white==uuubyte && white==uuurbyte && white==uuurrbyte && white==uuurrrbyte && white==uurrrbyte && 2035 white==urrrbyte && white==rrrbyte && white==drrrbyte && white==ddrrrbyte && white==uullbyte && 2036 white==ullbyte && white==uulbyte && white==ulbyte && white==uubyte && white==uurbyte && white==uurrbyte && 2037 white==urbyte && white==urrbyte && white==rrbyte && white==drrbyte ) 2038 return YES; 2039 } 2040 if ( white==lbyte && white==ubyte && white==dbyte ) 2041 { 2042 if ( white==uubyte && white==uuubyte && white==drbyte && white==ddrrbyte && dddrrrbyte && 2043 white==uuulbyte && white==uuullbyte && white==uuulllbyte && white==uulllbyte && white==ulllbyte && 2044 white==lllbyte && white==dlllbyte && white==ddlllbyte && white==dddlllbyte && white==dddllbyte && 2045 white==dddlbyte && white==dddbyte && white==dddrbyte && white==dddrrbyte && white==uullbyte && 2046 white==uulbyte && white==ullbyte && white==ulbyte && white==llbyte && white==dllbyte && white==dlbyte && 2047 white==ddllbyte && white==ddlbyte && white==ddrbyte && white==ddbyte ) 2048 return YES; 2049 if ( white==ddbyte && white==dddbyte && white==ulbyte && white==uullbyte && white==uuulllbyte && 2050 white==uuurrbyte && white==uuurbyte && white==uuubyte && white==uuulbyte && white==uuullbyte && 2051 white==uuulllbyte && white==uulllbyte && white==ulllbyte && white==lllbyte && white==dlllbyte && 2052 white==ddlllbyte && white==dddlllbyte && white==dddllbyte && white==dddlbyte && white==uullbyte && 2053 white==uulbyte && white==uubyte && white==uurbyte && white==ulbyte && white==ullbyte && white==llbyte && 2054 white==dllbyte && white==dlbyte && white==ddllbyte && white==ddlbyte ) 2055 return YES; 2056 } 2057 if ( white==lbyte && white==dbyte && white==rbyte ) 2058 { 2059 if ( white==llbyte && white==lllbyte && white==urbyte && white==uurrbyte && white==uuurrrbyte && 2060 white==dlllbyte && white==ddlllbyte && white==dddlllbyte && white==dddllbyte && white==dddlbyte && 2061 white==dddbyte && white==dddrbyte && white==dddrrbyte && white==dddrrrbyte && white==ddrrrbyte && 2062 white==drrrbyte && white==rrrbyte && white==urrrbyte && white==uurrrbyte && white==urrbyte && 2063 white==rrbyte && white==drbyte && white==drrbyte && white==ddrbyte && white==ddrrbyte && white==ddbyte && 2064 white==ddlbyte && white==dlbyte && white==dllbyte && white==ddllbyte ) 2065 return YES; 2066 if ( white==rrbyte && white==rrrbyte && white==ulbyte && white==uullbyte && white==uuulllbyte && 2067 white==uulllbyte && white==ulllbyte && white==lllbyte && white==dlllbyte && white==ddlllbyte && 2068 white==dddlllbyte && white==dddllbyte && white==dddlbyte && white==dddbyte && white==dddrbyte && 2069 white==dddrrbyte && white==dddrrrbyte && white==ddrrrbyte && white==drrrbyte && white==ullbyte && 2070 white==llbyte && white==dllbyte && white==dlbyte && white==drbyte && white==drrbyte && white==ddllbyte && 2071 white==ddlbyte && white==ddbyte && white==ddrbyte && white==ddrrbyte ) 2072 return YES; 2073 } 2074 2075 if ( !lbyte && !dbyte && !rbyte ) 2076 { unsigned char ullllbyte, llllbyte, dllllbyte, urrrrbyte, rrrrbyte, drrrrbyte; 2077 2078 llllbyte = *(data+(byteX-4)); rrrrbyte = *(data+(byteX+4)); 2079 ullllbyte = *(data+(byteX-4) - bytesPerRow); urrrrbyte = *(data+(byteX+4) - bytesPerRow); 2080 dllllbyte = *(data+(byteX-4) + bytesPerRow); drrrrbyte = *(data+(byteX+4) + bytesPerRow); 2081 2082 if ( !dlbyte && !drbyte && !llbyte && !dllbyte && !ddllbyte && !ddlbyte && !ddbyte && !ddrbyte && !ddrrbyte && !drrbyte && !rrbyte && !lllbyte && !dlllbyte && !ddlllbyte && !dddlllbyte && !dddllbyte && !dddlbyte && !dddbyte && !dddrbyte && !dddrrbyte && !dddrrrbyte && !ddrrrbyte && !drrrbyte && !rrrbyte && !ullllbyte && !llllbyte && !dllllbyte && !drrrrbyte && !rrrrbyte && !urrrrbyte ) 2083 return YES; 2084 } 2085 if ( !lbyte && !ubyte && !rbyte ) 2086 { unsigned char ullllbyte, llllbyte, dllllbyte, urrrrbyte, rrrrbyte, drrrrbyte; 2087 2088 llllbyte = *(data+(byteX-4)); rrrrbyte = *(data+(byteX+4)); 2089 ullllbyte = *(data+(byteX-4) - bytesPerRow); urrrrbyte = *(data+(byteX+4) - bytesPerRow); 2090 dllllbyte = *(data+(byteX-4) + bytesPerRow); drrrrbyte = *(data+(byteX+4) + bytesPerRow); 2091 2092 if ( !ulbyte && !urbyte && !llbyte && !ullbyte && !uullbyte && !uulbyte && !uubyte && !uurbyte && !uurrbyte && !urrbyte && !rrbyte && !lllbyte && !ulllbyte && !uulllbyte && !uuulllbyte && !uuullbyte && !uuulbyte && !uuubyte && !uuurbyte && !uuurrbyte && !uuurrrbyte && !uurrrbyte && !urrrbyte && !rrrbyte && !ullllbyte && !llllbyte && !dllllbyte && !drrrrbyte && !rrrrbyte && !urrrrbyte ) 2093 return YES; 2094 } 2095 if ( !ubyte && !dbyte && !rbyte ) 2096 { unsigned char uuuubyte, ddddbyte, uuuulbyte, uuuurbyte, ddddlbyte, ddddrbyte; 2097 2098 uuuubyte = *(data+byteX-(4*bytesPerRow)); ddddbyte = *(data+byteX+(4*bytesPerRow)); 2099 uuuulbyte = *(data+(byteX-1)-(4*bytesPerRow)); uuuurbyte = *(data+(byteX+1)-(4*bytesPerRow)); 2100 ddddlbyte = *(data+(byteX-1)+(4*bytesPerRow)); ddddrbyte = *(data+(byteX+1)+(4*bytesPerRow)); 2101 2102 if ( !urbyte && !drbyte && !uubyte && !uurbyte && !uurrbyte && !urrbyte && !rrbyte && !drrbyte && !ddrrbyte && !ddrbyte && !ddbyte && !uuubyte && !uuurbyte && !uuurrbyte && !uuurrrbyte && !uurrrbyte && !urrrbyte && !rrrbyte && !drrrbyte && !ddrrrbyte && !dddrrrbyte && !dddrrbyte && !dddrbyte && !dddbyte && !uuuulbyte && !uuuubyte && !uuuurbyte && !ddddlbyte && !ddddbyte && !ddddrbyte ) 2103 return YES; 2104 } 2105 if ( !ubyte && !dbyte && !lbyte ) 2106 { unsigned char uuuubyte, ddddbyte, uuuulbyte, uuuurbyte, ddddlbyte, ddddrbyte; 2107 2108 uuuubyte = *(data+byteX-(4*bytesPerRow)); ddddbyte = *(data+byteX+(4*bytesPerRow)); 2109 uuuulbyte = *(data+(byteX-1)-(4*bytesPerRow)); uuuurbyte = *(data+(byteX+1)-(4*bytesPerRow)); 2110 ddddlbyte = *(data+(byteX-1)+(4*bytesPerRow)); ddddrbyte = *(data+(byteX+1)+(4*bytesPerRow)); 2111 2112 if ( !ulbyte && !dlbyte && !uubyte && !uulbyte && !uullbyte && !ullbyte && !llbyte && !dllbyte && !ddllbyte && !ddlbyte && !ddbyte && !uuubyte && !uuulbyte && !uuullbyte && !uuulllbyte && !uulllbyte && !ulllbyte && !lllbyte && !dlllbyte && !ddlllbyte && !dddlllbyte && !dddllbyte && !dddlbyte && !dddbyte && !uuuulbyte && !uuuubyte && !uuuurbyte && !ddddlbyte && !ddddbyte && !ddddrbyte ) 2113 return YES; 2114 } 2115//white 2116 return NO; 2117} 2118 2119- (void)connectPtToLine:(int)indexL :(NSPoint)pt :(int*)endIsNearer :(int*)lineArray :(VPath*)path :(float)w 2120{ int edge=0; 2121 float minLineLength=81, minLineLenHV=7, len; 2122 NSPoint start, end; 2123 VGraphic *lineG = [[path list] objectAtIndex:lineArray[indexL]]; 2124 2125 if ( Abs(w) < 0.29 ) // < 0.1 mm 2126 { minLineLength = 25; minLineLenHV = 5; } 2127 if ( Abs(w) >= 0.29 ) // >= 0.1 mm 2128 { minLineLength = 36; minLineLenHV = 5; } 2129 if ( Abs(w) >= 0.86 ) // >= 0.3 mm 2130 { minLineLength = 49; minLineLenHV = 5; } 2131 if ( Abs(w) >= 1.42 ) // >= 0.5 mm 2132 { minLineLength = 64; minLineLenHV = 6; } 2133 if ( Abs(w) >= 2.83 ) // >= 1.0 mm 2134 { minLineLength = 81; minLineLenHV = 7; } 2135 if ( Abs(w) >= 5.6 ) // >= 2.0 mm 2136 { minLineLength = 100; minLineLenHV = 8; } 2137 2138 [(VLine*)lineG getVertices:&start :&end]; 2139 ( *endIsNearer ) ? (len=SqrDistPoints(start, pt)) : (len=SqrDistPoints(end, pt)); 2140 //lenOld = SqrDistPoints(start, end); 2141 if ( [self pointIsEdge:pt] ) 2142 edge = 1; 2143 if ( start.x == end.x && start.y == end.y ) // have at least started a new line 2144 { 2145 if ( edge && ![self pointIsEdge:start] ) 2146 { [lineG setSelected:YES]; 2147 [(VLine*)lineG setVertices:pt :pt]; 2148 } 2149 else [(VLine*)lineG setVertices:start :pt]; 2150 } 2151 else if ( (start.x == end.x && Diff(start.y, end.y) >= minLineLenHV) || 2152 (start.y == end.y && Diff(start.x, end.x) >= minLineLenHV) ) 2153 { // vertical lines not so long ! 2154 if ( /*len > lenOld &&*/ ((len <= minLineLength && start.x == end.x && pt.x == start.x) 2155 || (start.y == end.y && pt.y == start.y)) ) 2156 { 2157 if ( [lineG isSelected] && 2158 ((!(*endIsNearer) && [self pointIsEdge:start]) || (endIsNearer && [self pointIsEdge:end])) ) 2159 { // else we would change the edge ! 2160 lineG = [VLine line]; 2161 [lineG setSelected:YES]; [lineG setColor:[NSColor blackColor]]; [lineG setWidth:0]; 2162 [(VLine*)lineG setVertices:pt :pt]; 2163 [[path list] addObject:lineG]; *endIsNearer = 1; 2164 lineArray[indexL] = (int)[[path list] count]-1; // replace value at indexL with new line index 2165 } 2166 else // connect 2167 { if ( *endIsNearer ) [(VLine*)lineG setVertices:start :pt]; 2168 else [(VLine*)lineG setVertices:pt :end]; // here other direction is ok 2169 if ( edge ) 2170 { [lineG setSelected:YES]; 2171 lineG = [VLine line]; [lineG setSelected:YES]; 2172 [lineG setColor:[NSColor blackColor]]; [lineG setWidth:0]; 2173 [(VLine*)lineG setVertices:pt :pt]; *endIsNearer = 1; 2174 [[path list] addObject:lineG]; 2175 lineArray[indexL] = (int)[[path list] count]-1; // replace value at indexL with new line index 2176 } 2177 } 2178 } 2179 else // if ( len <= lenOld ) 2180 { lineG = [VLine line]; ( edge ) ? [lineG setSelected:YES] : [lineG setSelected:NO]; 2181 [lineG setColor:[NSColor blackColor]]; [lineG setWidth:0]; 2182 if ( *endIsNearer ) [(VLine*)lineG setVertices:end :pt]; 2183 else { [(VLine*)lineG setVertices:start :pt]; *endIsNearer = 1; } 2184 [[path list] addObject:lineG]; 2185 lineArray[indexL] = (int)[[path list] count]-1; // replace value at indexL with new line index 2186 } 2187 } 2188 else // no vertical / horicontal line 2189 { 2190 if ( /*len > lenOld &&*/ len <= minLineLength ) 2191 { 2192 if ( [lineG isSelected] && // start or end is edge point - do not change !!! 2193 ((!(*endIsNearer) && [self pointIsEdge:start]) || (*endIsNearer && [self pointIsEdge:end])) ) 2194 { // else we would change the edge ! 2195 lineG = [VLine line]; 2196 [lineG setSelected:YES]; [lineG setColor:[NSColor blackColor]]; [lineG setWidth:0]; 2197 [(VLine*)lineG setVertices:pt :pt]; *endIsNearer = 1; 2198 [[path list] addObject:lineG]; 2199 lineArray[indexL] = (int)[[path list] count]-1; // replace value at indexL with new line index 2200 } 2201 else 2202 { if ( *endIsNearer ) [(VLine*)lineG setVertices:start :pt]; 2203 else { [(VLine*)lineG setVertices:end :pt]; *endIsNearer = 1; }// change direction ! 2204 if ( edge ) 2205 { [lineG setSelected:YES]; 2206 lineG = [VLine line]; 2207 [lineG setSelected:YES]; [lineG setColor:[NSColor blackColor]]; [lineG setWidth:0]; 2208 [(VLine*)lineG setVertices:pt :pt]; *endIsNearer = 1; 2209 [[path list] addObject:lineG]; 2210 lineArray[indexL] = (int)[[path list] count]-1; // replace value at indexL with new line index 2211 } 2212 } 2213 } 2214#if 0 2215 else if ( len <= lenOld ) 2216 { lineG = [VLine line]; ( edge ) ? [lineG setSelected:YES] : [lineG setSelected:NO]; 2217 [lineG setColor:[NSColor blackColor]]; [lineG setWidth:0]; 2218 [(VLine*)lineG setVertices:pt :pt]; *endIsNearer = 1; 2219 [[path list] addObject:lineG]; 2220 lineArray[indexL] = (int)[[path list] count]-1; // replace value at indexL with new line index 2221 return; 2222 } 2223#endif 2224 else 2225 { 2226 if ( [lineG isSelected] && 2227 ((!(*endIsNearer) && [self pointIsEdge:start]) || (endIsNearer && [self pointIsEdge:end])) ) 2228 { // else we would change the edge ! 2229 lineG = [VLine line]; 2230 [lineG setSelected:YES]; [lineG setColor:[NSColor blackColor]]; [lineG setWidth:0]; 2231 [(VLine*)lineG setVertices:pt :pt]; *endIsNearer = 1; 2232 [[path list] addObject:lineG]; 2233 lineArray[indexL] = (int)[[path list] count]-1; // replace value at indexL with new line index 2234 } 2235 else 2236 { if ( edge ) 2237 { if ( *endIsNearer ) { [(VLine*)lineG setVertices:start :pt]; end=pt; } 2238 else { [(VLine*)lineG setVertices:end :pt]; start = pt; } 2239 [lineG setSelected:YES]; 2240 } 2241 lineG = [VLine line]; ( edge ) ? [lineG setSelected:YES] : [lineG setSelected:NO]; 2242 [lineG setColor:[NSColor blackColor]]; [lineG setWidth:0]; 2243 if ( *endIsNearer ) [(VLine*)lineG setVertices:end :pt]; 2244 else { [(VLine*)lineG setVertices:start :pt]; *endIsNearer = 1; } 2245 [[path list] addObject:lineG]; 2246 lineArray[indexL] = (int)[[path list] count]-1; // replace value at indexL with new line index 2247 } 2248 } 2249 } 2250} 2251 2252/* modified: 2008-02-08 2253 * go on building the path with these new points 2254 */ 2255- (void)buildPath:(VPath*)path :(NSPoint*)pts :(int)pCnt :(float)w :(int*)lineArray :(int*)lineCnt 2256{ int i, j, k, myPcnt=pCnt, startNewLine = 0; // lineArray[pCnt*2], lineCnt=0 2257 NSPoint start, end, s, e; 2258 VGraphic *lineG, *lineG2; 2259 NSColor *nxBlack = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 2260 2261 if ( ![[path list] count] && pCnt) 2262 { 2263 if ( pCnt > 1 && Diff(pts[0].x, pts[1].x) <= 1 ) // waagerechte ? 2264 { for (i=0; i<2; i++) 2265 { lineG = [VLine line]; ( [self pointIsEdge:pts[0]] ) ? [lineG setSelected:YES] : [lineG setSelected:NO]; 2266 [lineG setColor:nxBlack]; [lineG setWidth:0]; 2267 [(VLine*)lineG setVertices:pts[0] :pts[0]]; 2268 [[path list] addObject:lineG]; 2269 lineArray[(*lineCnt)++] = i; 2270 for (k=0; k<myPcnt-1; k++) 2271 pts[k] = pts[k+1]; 2272 myPcnt--; 2273 } 2274 } 2275 else // start two lines ! 2276 { for (i=0; i<2; i++) 2277 { lineG = [VLine line]; ( [self pointIsEdge:pts[0]] ) ? [lineG setSelected:YES] : [lineG setSelected:NO]; 2278 [lineG setColor:nxBlack]; [lineG setWidth:0]; 2279 [(VLine*)lineG setVertices:pts[0] :pts[0]]; 2280 [[path list] addObject:lineG]; 2281 lineArray[(*lineCnt)++] = i; 2282 } 2283 for (k=0; k<myPcnt-1; k++) 2284 pts[k] = pts[k+1]; 2285 myPcnt--; 2286 } 2287 } 2288 2289 while ( myPcnt > 0 ) 2290 { 2291 // connect pts to lines 2292 for (i=0; i<(*lineCnt); i++) 2293 { int endIsNearer=-1, indexE=-1, indexS=-1, secondLine=0, endIsNearer2=0; 2294 int fromLeftToRight=1, stopForLine2 = 0, secDiff=0, doNotRemovePtJ = 0, rowDiff=0; 2295 NSPoint stopPt = NSZeroPoint, lastRowPt; 2296 2297 if ( myPcnt <= 0 && startNewLine ) 2298 break; // else we must remove lines with no point !! 2299 2300 lineG=[[path list] objectAtIndex:lineArray[i]]; 2301 [(VLine*)lineG getVertices:&start :&end]; 2302 // first get nearest pt to lineG 2303 for (j=0; j<myPcnt; j++) 2304 { 2305 if ( indexS == -1 && end.y >= start.y && // indexS allways set -> do not set indexE !!! 2306 Diff(pts[j].x, end.x) <= 1 && Diff(pts[j].y, end.y) <= 1 && 2307 Diff(pts[j].x, end.x) <= Diff(pts[j].x, start.x) && end.y >= start.y && 2308 ((indexE == -1 || (Diff(pts[j].x, end.x) < Diff(pts[indexE].x, end.x))) || 2309 (indexE != -1 && Diff(pts[j].x, end.x) == Diff(pts[indexE].x, end.x) && end.x > start.x)) ) 2310 // line from le to ri -> prefer ri pt 2311 { indexE = j; endIsNearer = 1; } 2312 else if ( indexE == -1 && start.y >= end.y && // (start.x != end.x || start.y != end.y) && 2313 Diff(pts[j].x, start.x) <= 1 && Diff(pts[j].y, start.y) <= 1 && 2314 Diff(pts[j].x, start.x) <= Diff(pts[j].x, end.x) && start.y >= end.y && 2315 ((indexS == -1 || (Diff(pts[j].x, start.x) < Diff(pts[indexS].x, start.x))) || 2316 (indexS != -1 && Diff(pts[j].x, start.x) == Diff(pts[indexS].x, start.x) && start.x > end.x)) ) 2317 { indexS = j; endIsNearer = 0; } 2318 else if ( (end.y > start.y && pts[j].x > end.x+1) || (start.y > end.y && pts[j].x > start.x+1) || 2319 (end.y == start.y && pts[j].x > end.x+1 && pts[j].x > start.x+1) ) 2320 break; 2321 } 2322 if ( indexE == -1 && indexS == -1 ) 2323 { int m; 2324 if ( !(start.x == end.x && start.y == end.y && start.y == pts[0].y) && !startNewLine ) 2325 { for (m=i; m<(*lineCnt)-1; m++) // sort out line from lineArray 2326 lineArray[m] = lineArray[m+1]; 2327 (*lineCnt)--; 2328 i--; // else we jump over one line 2329 } 2330 continue; 2331 } 2332 ( endIsNearer ) ? (j = indexE) : (j=indexS); // must set j !!!!!!!!!!!!!!!!!!! 2333 2334 // check if pt row 2335 rowDiff = 0; 2336 for (k=j; k<myPcnt-1 && i<(*lineCnt)-1; k++) 2337 { if ( Diff(pts[k].x, pts[k+1].x) <= 1 ) 2338 { rowDiff = (k+1)-j; lastRowPt = pts[k+1]; } 2339 else break; 2340 } 2341 rowDiff += 2; // min of two - if one pt and two lines !! 2342 2343 // look for a second line right of lineG with rowDist distance 2344 if ( i < (*lineCnt)-1 ) 2345 { NSPoint tp; 2346 lineG2 = [[path list] objectAtIndex:lineArray[i+1]]; 2347 [(VLine*)lineG2 getVertices:&s :&e]; 2348 if ( s.y > e.y ) tp = s; 2349 else if ( e.y > s.y ) tp = e; 2350 else tp = e; // if ( pts[j].x <= s.x && pts[j].x <= e.x ) - only possible ! 2351 if ( ( endIsNearer && (secDiff=Diff( end.x, tp.x)) <= rowDiff) || 2352 (!endIsNearer && (secDiff=Diff(start.x, tp.x)) <= rowDiff) ) 2353 { secondLine = 1; secDiff += 2; 2354 endIsNearer2 = 1; // allways the end 2355 } 2356 } 2357 // set connect direction and j if necessary !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2358 // pts on both sides of pts[j] 2359 if ( ((!secondLine && j-1 >= 0 && Diff(pts[j-1].x, pts[j].x) <= 1) || 2360 (secondLine && j-1 >= 0 && Diff(pts[j-1].x, pts[j].x) <= secDiff)) && 2361 ((!secondLine && j+1 < myPcnt && Diff(pts[j+1].x, pts[j].x) <= 1) || 2362 (secondLine && j+1 < myPcnt && Diff(pts[j+1].x, pts[j].x) <= secDiff)) ) 2363 { 2364 // look for direction of line ??? 2365 if ( (endIsNearer && end.x <= start.x) || (!endIsNearer && start.x <= end.x) || 2366 (secondLine && e.x <= s.x) ) 2367 fromLeftToRight = 0; // start right - at j 2368 else if ( (endIsNearer && end.x > start.x) || (!endIsNearer && start.x > end.x) || 2369 (secondLine && e.x > s.x) ) 2370 fromLeftToRight = 1; // start left - at j until stopPt !! 2371 } 2372 // pts left of pts[j] 2373 else if ( (!secondLine && j-1 >= 0 && Diff(pts[j-1].x, pts[j].x) <= 1) || 2374 (secondLine && j-1 >= 0 && Diff(pts[j-1].x, pts[j].x) <= secDiff) ) 2375 { 2376 fromLeftToRight = 0; 2377 if ( secondLine && Diff(pts[j].x, pts[j-1].x) <= 1 ) 2378 doNotRemovePtJ = 1; // need j also for second line 2379 else if ( secondLine ) 2380 j = j-1; // must connect one pt to second line ! 2381 if ( !secondLine && ((endIsNearer && start.x < end.x) || (!endIsNearer && end.x < start.x)) && 2382 [self pointIsEdge:pts[j]] ) // direction change !! 2383 { int m; 2384 lineG = [VLine line]; // start a new line !!! 2385 [lineG setSelected:YES]; [lineG setColor:nxBlack]; [lineG setWidth:0]; 2386 [(VLine*)lineG setVertices:pts[j] :pts[j]]; start = end = pts[j]; 2387 [[path list] addObject:lineG]; 2388 lineArray[i] = (int)[[path list] count]-1; // replace line index 2389 for (m=j; m<myPcnt-1; m++) // sort out pt j from pts 2390 pts[m] = pts[m+1]; 2391 myPcnt--; 2392 } 2393 } 2394 // pts right of pts[j] 2395 else if ( (!secondLine && j+1 < myPcnt && Diff(pts[j+1].x, pts[j].x) <= 1) || 2396 (secondLine && j+1 < myPcnt && Diff(pts[j+1].x, pts[j].x) <= secDiff) ) 2397 { 2398 fromLeftToRight = 1; 2399 if ( !secondLine && ((endIsNearer && start.x > end.x) || (!endIsNearer && end.x > start.x)) && 2400 [self pointIsEdge:pts[j]] ) 2401 { int m; 2402 lineG = [VLine line]; // start a new line !!! 2403 [lineG setSelected:YES]; [lineG setColor:nxBlack]; [lineG setWidth:0]; 2404 [(VLine*)lineG setVertices:pts[j] :pts[j]]; start = end = pts[j]; 2405 [[path list] addObject:lineG]; 2406 lineArray[i] = (int)[[path list] count]-1; // replace line index 2407 for (m=j; m<myPcnt-1; m++) // sort out pt j from pts 2408 pts[m] = pts[m+1]; 2409 myPcnt--; 2410 } 2411 } 2412 else if ( secondLine && ((s.x == e.x && s.y == e.y) || // set point to new/right line !! 2413 (start.y == end.y && pts[j].y > end.y)) ) continue; 2414 else if ( secondLine && ((endIsNearer && (start.x != s.x || start.y != s.y)) || 2415 (!endIsNearer && (end.x != e.x || end.y != e.y))) ) 2416 doNotRemovePtJ = 1; // only one pt for both lines - for peaks at top /\ ! 2417 2418 // search stop pt for second line !!! 2419 if ( fromLeftToRight && secondLine && !doNotRemovePtJ && j+1 < myPcnt ) 2420 { 2421 if ( ((endIsNearer && start.x > end.x) || (!endIsNearer && end.x > start.x)) ) 2422 { stopPt = pts[j+1]; stopForLine2 = 1; } // only one pt to connect for lineG !! - other direction 2423 else 2424 { // get nearest pt to second line - is our stop PT 2425 indexE = indexS = -1; 2426 for (k=j+1; k<myPcnt; k++) 2427 { 2428 if ( e.y >= s.y && Diff(pts[k].x, e.x) <= 1 && Diff(pts[k].y, e.y) <= 1 && 2429 Diff(pts[k].x, e.x) <= Diff(pts[k].x, s.x) && e.y >= s.y ) 2430 //(indexE == -1 || (Diff(pts[k].x, e.x) <= Diff(pts[indexE].x, e.x))) // need right pt 2431 { stopPt = pts[k]; indexE = k; endIsNearer2 = 1; } 2432 else if ( indexE == -1 && s.y >= e.y && // (s.x != e.x || s.y != e.y) && 2433 Diff(pts[k].x, s.x) <= 1 && Diff(pts[k].y, s.y) <= 1 && 2434 Diff(pts[k].x, s.x) <= Diff(pts[k].x, e.x) && s.y >= e.y ) 2435 //(indexS == -1 || (Diff(pts[k].x, s.x) <= Diff(pts[indexS].x, s.x))) 2436 { stopPt = pts[k]; indexS = k; endIsNearer2 = 0; } 2437 else if ( (e.y > s.y && pts[j].x > e.x+1) || (s.y > e.y && pts[j].x > s.x+1) || 2438 (e.y == s.y && pts[j].x > e.x+1 && pts[j].x > s.x+1) ) 2439 break; 2440 } 2441 // if ( indexE == -1 && indexS == -1 ) 2442 // printf("no StopPt found ???\n"); // ?????????????????????????????????????????? 2443 if ( indexE != -1 || indexS != -1 ) 2444 stopForLine2 = 1; // must stop connect to rest pts for second line 2445 } 2446 } 2447 2448 // connect pts to line(s) 2449 if ( fromLeftToRight && !stopForLine2 ) 2450 { int m; 2451 for (k=j; k<myPcnt; k++) 2452 { 2453 if ( ( endIsNearer && Diff(pts[k].x, end.x) <= 1) || 2454 (!endIsNearer && Diff(pts[k].x, start.x) <= 1) ) 2455 { [self connectPtToLine:i :pts[k] :&endIsNearer :lineArray :path :w]; 2456 lineG = [[path list] objectAtIndex:lineArray[i]]; // must set lineG new !!! 2457 [(VLine*)lineG getVertices:&start :&end]; // must set start / end new !!! 2458 if ( !doNotRemovePtJ ) 2459 { for (m=k; m<myPcnt-1; m++) // sort out pt j from pts 2460 pts[m] = pts[m+1]; 2461 myPcnt--; 2462 k--; 2463 } 2464 else doNotRemovePtJ = 0; // only first pt 2465 } 2466 else break; 2467 } 2468 } 2469 else if ( fromLeftToRight && stopForLine2 ) 2470 { int m; 2471 for (k=j; k<myPcnt; k++) 2472 { 2473 if ( (pts[k].x != stopPt.x || pts[k].y != stopPt.y) && // do not connect stopPt 2474 (( endIsNearer && Diff(pts[k].x, end.x) <= 1) || 2475 (!endIsNearer && Diff(pts[k].x, start.x) <= 1)) ) 2476 { [self connectPtToLine:i :pts[k] :&endIsNearer :lineArray :path :w]; 2477 lineG = [[path list] objectAtIndex:lineArray[i]]; // must set lineG new !!! 2478 [(VLine*)lineG getVertices:&start :&end]; // must set start / end new !!! 2479 if ( !doNotRemovePtJ ) 2480 { for (m=k; m<myPcnt-1; m++) // sort out pt j from pts 2481 pts[m] = pts[m+1]; 2482 myPcnt--; 2483 k--; 2484 } 2485 else doNotRemovePtJ = 0; 2486 } 2487 else break; 2488 } 2489 } 2490 else if ( !fromLeftToRight ) // connect pts from right to left start with k -> first line if we have two lines ! 2491 { int m; 2492 for (k=j; k>=0; k--) 2493 { 2494 if ( ( endIsNearer && Diff(pts[k].x, end.x) <= 1) || 2495 (!endIsNearer && Diff(pts[k].x, start.x) <= 1) ) 2496 { [self connectPtToLine:i :pts[k] :&endIsNearer :lineArray :path :w]; 2497 lineG = [[path list] objectAtIndex:lineArray[i]]; // must set lineG new !!! 2498 [(VLine*)lineG getVertices:&start :&end]; // must set start / end new !!! 2499 if ( !doNotRemovePtJ ) 2500 { for (m=k; m<myPcnt-1; m++) // sort out pt j from pts 2501 pts[m] = pts[m+1]; 2502 myPcnt--; 2503 } 2504 else doNotRemovePtJ = 0; 2505 } 2506 else break; 2507 } 2508 } 2509 } 2510 // start new lines - with one not connected pt -> one more the same !! 2511 if ( myPcnt > 0 ) 2512 { int m, rightPtI=0; 2513 2514 // check if pt row 2515 for (k=0; k<myPcnt-1; k++) 2516 { if ( Diff(pts[k].x, pts[k+1].x) <= 1 ) 2517 { rightPtI = k+1; } 2518 else 2519 break; 2520 } 2521 if ( rightPtI && [self pointIsEdge:pts[rightPtI]] ) 2522 { 2523 lineG = [VLine line]; [lineG setSelected:YES]; 2524 [lineG setColor:nxBlack]; [lineG setWidth:0]; 2525 [(VLine*)lineG setVertices:pts[rightPtI] :pts[rightPtI]]; 2526 [[path list] addObject:lineG]; 2527 lineArray[(*lineCnt)++] = (int)[[path list] count]-1; // add line index to lineArray 2528 for (m=rightPtI; m<myPcnt-1; m++) // sort out pts[r] j from pts 2529 pts[m] = pts[m+1]; 2530 myPcnt--; 2531 2532 lineG = [VLine line]; 2533 ( [self pointIsEdge:pts[rightPtI-1]] ) ? [lineG setSelected:YES] : [lineG setSelected:NO]; 2534 [lineG setColor:nxBlack]; [lineG setWidth:0]; 2535 [(VLine*)lineG setVertices:pts[rightPtI-1] :pts[rightPtI-1]]; 2536 [[path list] addObject:lineG]; 2537 lineArray[(*lineCnt)++] = (int)[[path list] count]-1; // add line index to lineArray 2538 for (m=rightPtI-1; m<myPcnt-1; m++) // sort out pts[...-1] j from pts 2539 pts[m] = pts[m+1]; 2540 myPcnt--; 2541 } 2542 else 2543 { lineG = [VLine line]; ( [self pointIsEdge:pts[0]] ) ? [lineG setSelected:YES] : [lineG setSelected:NO]; 2544 [lineG setColor:nxBlack]; [lineG setWidth:0]; 2545 [(VLine*)lineG setVertices:pts[0] :pts[0]]; 2546 [[path list] addObject:lineG]; 2547 lineArray[(*lineCnt)++] = (int)[[path list] count]-1; // add line index to lineArray 2548 if ( [self pointIsEdge:pts[0]] ) 2549 { 2550 if ( myPcnt > 1 && Diff(pts[0].x, pts[1].x) <= 1 ) // pts[1] is second line !!! 2551 { for (m=0; m<myPcnt-1; m++) // sort out pts[0] j from pts 2552 pts[m] = pts[m+1]; 2553 myPcnt--; 2554 } 2555 lineG = [VLine line];[lineG setSelected:YES]; 2556 [lineG setColor:nxBlack]; [lineG setWidth:0]; 2557 [(VLine*)lineG setVertices:pts[0] :pts[0]]; 2558 [[path list] addObject:lineG]; 2559 lineArray[(*lineCnt)++] = (int)[[path list] count]-1; // add line index to lineArray 2560 } 2561 for (m=0; m<myPcnt-1; m++) // sort out pts[0] j from pts 2562 pts[m] = pts[m+1]; 2563 myPcnt--; 2564 } 2565 startNewLine = 1; // we do not remove lines in second part to connect rest points 2566 2567 // sort line indexes from left line to right line 2568 for (i=0; i<(*lineCnt)-1; i++) 2569 { VGraphic *g1=[[path list] objectAtIndex:lineArray[i]]; 2570 2571 [(VLine*)g1 getVertices:&start :&end]; 2572 for (j=i+1; j<(*lineCnt); j++) 2573 { VGraphic *g2=[[path list] objectAtIndex:lineArray[j]]; 2574 2575 [(VLine*)g2 getVertices:&s :&e]; 2576 if ( (e.y > s.y && e.x < ((end.y > start.y) ? (end.x) : (start.x))) || 2577 (e.y < s.y && s.x < ((end.y > start.y) ? (end.x) : (start.x))) || 2578 (e.y == s.y && s.x < ((end.y > start.y) ? (end.x) : (start.x)) && 2579 e.x < ((end.y > start.y) ? (end.x) : (start.x))) ) 2580 { int bufI=lineArray[i]; 2581 lineArray[i] = lineArray[j]; 2582 lineArray[j] = bufI; 2583 g1 = [[path list] objectAtIndex:lineArray[i]]; 2584 [(VLine*)g1 getVertices:&start :&end]; // set g1 new ! 2585 } 2586 } 2587 } 2588 } 2589 else break; 2590 } 2591} 2592 2593/* */ 2594- (void)optimizePath:(VPath*)path :(int)w 2595{ int i1, i2, changeI, startIndex=0, index2=0, yMin, iDiff, openPath = 0; 2596 float startDistance=MAXCOORD, dist=(w*w), d1, d2, d, l1eY; 2597 float distHalf/*=(w/2)*(w/2)*/, distQuarter;//=(w/8)*(w/8); 2598 NSPoint l1S, l1E, l2S, l2E; 2599 VLine *l1, *l2; 2600 2601 if ( ![[path list] count] ) 2602 return; 2603 2604 distHalf = 100; distQuarter = 25; dist = 121; 2605 2606 l1 = [[path list] objectAtIndex:0]; 2607 [l1 getVertices:&l1S :&l1E]; 2608 yMin = l1S.y; 2609 for (i1 = 0; i1<(int)[[path list] count]-1; i1++) 2610 { l1=[[path list] objectAtIndex:i1]; 2611 2612 startDistance = MAXCOORD; 2613 changeI = i1+1; 2614 [l1 getVertices:&l1S :&l1E]; 2615 2616 if ( Diff(l1S.x, l1E.x) == 0 && Diff(l1S.y, l1E.y) == 0 ) 2617 { 2618 [[path list] removeObjectAtIndex:i1]; 2619 if ( startIndex > i1 ) 2620 startIndex--; 2621 i1 = ( startIndex == i1 ) ? (i1 - 1) : (i1 - 2); 2622 continue; 2623 } 2624 l1eY = l1E.y + distHalf; 2625 /* get index2 */ 2626 index2 = i1+1; 2627 if ( !openPath && i1 > 50 && (iDiff=((int)[[path list] count]-1 - (i1+1))) > 100 ) 2628 { int j, testI, l1eYMin = l1E.y - 10, prevTI=iDiff, diff; 2629 2630 testI = iDiff/2.0; 2631 for (j=0; j<iDiff; j++) 2632 { 2633 if ( i1+testI < i1+1 || i1+testI > (int)[[path list] count]-1) 2634 printf("PathContour.m: -optimizePath: darf nicht sein 2\n"); 2635 l2=[[path list] objectAtIndex:i1+testI]; 2636 [l2 getVertices:&l2S :&l2E]; 2637 if ( Max(l2S.y, l2E.y) < l1eYMin || l2S.y == yMin || l2E.y == yMin ) 2638 { 2639 if ( Diff(Max(l2S.y, l2E.y), l1E.y) < distHalf ) 2640 { index2 = i1+testI; break; } 2641 else if ( testI > iDiff-100 ) 2642 { index2 = i1+testI; break; } 2643 else // up 2644 { diff = Diff(prevTI, testI)/2.0; 2645 prevTI = testI; 2646 testI = testI + diff; 2647 } 2648 } 2649 else if ( testI <= 50 ) 2650 { index2 = i1+1; break; } 2651 else // down 2652 { diff = Diff(prevTI, testI)/2.0; 2653 prevTI = testI; 2654 testI = testI - diff; 2655 } 2656 } 2657 if ( index2 < i1+1 || index2 > (int)[[path list] count]-1 ) 2658 { 2659 index2 = i1+1; 2660 printf("PathContour.m: -optimizePath: darf nicht sein\n"); 2661 } 2662 } 2663 2664 for (i2=index2; i2<(int)[[path list] count]; i2++) 2665 { VLine *l2=[[path list] objectAtIndex:i2]; 2666 2667 [l2 getVertices:&l2S :&l2E]; 2668 d1 = SqrDistPoints(l1E, l2S); d2 = SqrDistPoints(l1E, l2E); 2669// if ( (d1 <= dist && d1 < startDistance) || (d2 <= dist && d2 < startDistance) ||) 2670 if ( (d1 < startDistance || d2 < startDistance) || 2671 ((d1 == startDistance || d2 == startDistance) && ([self pointIsEdge:l2S] || [self pointIsEdge:l2E])) ) 2672 { 2673 if ( d2 < d1 ) 2674 { startDistance = d2; 2675 [l2 setVertices:l2E :l2S]; /* change direction of l2 */ 2676 } 2677 else 2678 startDistance = d1; 2679 changeI = i2; 2680 if ( Diff(startDistance, 0.0) <= 0 ) 2681 break; 2682 } 2683 if ( l2S.y > l1eY && l2E.y > l1eY ) 2684 break; 2685 } 2686 if ( startDistance ) /* close hole */ 2687 { l2 = [[path list] objectAtIndex:changeI]; 2688 [(VLine*)l2 getVertices:&l2S :&l2E]; 2689 if ( (d=SqrDistPoints(l1E, l2S)) && d < distQuarter ) 2690 { if ( [self pointIsEdge:l2S] ) [l1 setVertices:l1S :l2S]; 2691 else [l2 setVertices:l1E :l2E]; 2692 if ( openPath ) 2693 openPath = 0; 2694 } 2695 else 2696 { VLine *l3 = [[path list] objectAtIndex:startIndex]; 2697 float d3 = SqrDistPoints(l1E, [l3 pointWithNum:0]); 2698 2699 /* close with l2 */ 2700 if ( d && d <= dist && d < d3) // distance to nextG must be smaller than to startG 2701 { VGraphic *lineG = [VLine line]; 2702 NSColor *nxBlack=[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 2703 2704 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 2705 [(VLine*)lineG setVertices:l1E :l2S]; 2706 [[path list] insertObject:lineG atIndex:i1+1]; 2707 i1 += 1; changeI += 1; 2708 } 2709 else if ( i1-startIndex == 0 ) 2710 { 2711 /* one single Graphic */ 2712 [[path list] removeObjectAtIndex:i1]; 2713 i1 --; 2714 continue; 2715 } 2716 /* closeTo startG */ 2717 else if ( d3 < d && d3 < distQuarter) // close to startG 2718 { if ( [self pointIsEdge:[l3 pointWithNum:0]] ) [l1 setVertices:l1S :[l3 pointWithNum:0]]; 2719 else [l3 setVertices:l1E :[l3 pointWithNum:MAXINT]]; 2720 startIndex = i1+1; 2721 } 2722 else if ( d3 < d && d3 < dist) // close to startG 2723 { VGraphic *lineG = [VLine line]; 2724 NSColor *nxBlack=[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 2725 2726 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 2727 [(VLine*)lineG setVertices:l1E :[l3 pointWithNum:0]]; 2728 [[path list] insertObject:lineG atIndex:i1+1]; 2729 i1 += 1; changeI += 1; 2730 startIndex = i1+1; 2731 } 2732 else if (d3 < d && d < dist) 2733 startIndex = i1+1; 2734 else if ( i1-startIndex == 1 ) 2735 { 2736 /* two graphics which cant be closed */ 2737 [[path list] removeObjectAtIndex:i1]; 2738 i1--; 2739 [[path list] removeObjectAtIndex:i1]; 2740 i1 --; 2741 continue; 2742 } 2743 else if ( openPath && d3 < d ) // close to StartG 2744 { VGraphic *lineG = [VLine line]; 2745 NSColor *nxBlack=[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 2746 2747 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 2748 [(VLine*)lineG setVertices:l1E :[l3 pointWithNum:0]]; 2749 [[path list] insertObject:lineG atIndex:i1+1]; 2750 i1 += 1; changeI += 1; 2751 startIndex = i1+1; 2752 openPath = 0; 2753 } 2754 else if ( openPath && d < d3 ) // close to l2 2755 { VGraphic *lineG = [VLine line]; 2756 NSColor *nxBlack=[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 2757 2758 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 2759 [(VLine*)lineG setVertices:l1E :l2S]; 2760 [[path list] insertObject:lineG atIndex:i1+1]; 2761 i1 += 1; changeI += 1; 2762 openPath = 0; 2763 } 2764 else if ( !openPath && d > dist && d3 > dist ) 2765 { openPath++; 2766 i1--; 2767 continue; 2768 } 2769 } 2770// if ( !openPath && startDistance > dist ) 2771// startIndex = i1+1; 2772 } 2773 else if ( openPath ) 2774 openPath = 0; 2775 /* if the nearest element is not the next_in_list */ 2776 if ( changeI != (i1+1) ) 2777 { VGraphic *gCh=[[path list] objectAtIndex:changeI]; 2778 2779 [[path list] removeObject:gCh]; 2780 [[path list] insertObject:gCh atIndex:i1+1]; 2781 } 2782 } 2783 /* close hole from last to start element */ 2784 { l1=[[path list] objectAtIndex:(int)[[path list] count]-1]; 2785 l2= [[path list] objectAtIndex:startIndex]; 2786 2787 if ( [[path list] count]-startIndex == 1 ) 2788 [[path list] removeObjectAtIndex:(int)[[path list] count]-1]; 2789 else 2790 { 2791 [l1 getVertices:&l1S :&l1E]; 2792 [l2 getVertices:&l2S :&l2E]; 2793 if ( (d=SqrDistPoints(l1E, l2S)) && d < distQuarter ) 2794 { if ( [self pointIsEdge:l2S] ) [l1 setVertices:l1S :l2S]; 2795 else [l2 setVertices:l1E :l2E]; 2796 } 2797 else if ( d /*&& d <= dist*/ ) 2798 { VGraphic *lineG = [VLine line]; 2799 NSColor *nxBlack=[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 2800 2801 [lineG setColor:nxBlack]; [lineG setWidth:0]; [lineG setSelected:NO]; 2802 [(VLine*)lineG setVertices:l1E :l2S]; 2803 [[path list] addObject:lineG]; 2804 } 2805 } 2806 } 2807 /* unite lines with same gradients */ 2808 [self smoothenLinesInPath:path]; 2809 [self smoothenLinesInPath:path]; 2810 [self uniteLinesWithSameGradient:path :w]; 2811 2812 return; 2813} 2814 2815/* 2816 * modified: 2010-03-03 (setDirectionCCW:) 2817 * 2008-02-08 2818 * get contour of path using a bitmap algorithm 2819 * return the calculated path 2820 */ 2821- (VPath*)contourPath:(VPath*)oPath width:(float)width 2822{ VPath *path, *oPathCopy; 2823 NSRect conRect, bounds, rect; 2824 id win, conView; 2825 float w=width+[oPath width], w2, bytes, scale = 1, maxBytes = 110250000, wi, h, s; 2826 int x, y, right, height, start, w2Int, bytesPerRowHalf, quality = 2; 2827 NSColor *nxWhite, *nxBlack; 2828 NSPoint moveP, center; 2829 NSBitmapImageRep *bitmapImage; 2830 2831#if DEBUG_CONTUR 2832 NSColor *nxGray; 2833 nxGray = [NSColor colorWithCalibratedRed:0.335 green:0.335 blue:0.335 alpha:1.0]; 2834printf("%s Hour.Min.Sec Start\n", [[[NSCalendarDate date] descriptionWithCalendarFormat:@"%H.%M.%S"] cString]); 2835#endif 2836 2837 nxBlack = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 2838 nxWhite = [NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0]; 2839 2840 path = [VPath path]; 2841 [path setColor:[oPath color]]; 2842 [path setFilled:NO]; 2843 [path setWidth:0]; 2844 [path setSelected:NO]; 2845 2846 if ( !w ) 2847 return path; 2848 2849 /* copy self make it white */ 2850 oPathCopy = [oPath copy]; 2851 [oPathCopy setFilled:YES]; 2852 [oPathCopy setWidth:0]; 2853 2854 /* calc content rect size / scale factor 2855 * to get not more than 20 MB memory 2856 * the bounds of the path: width*height / 8(bit) * 2(color deepnes) 2857 */ 2858 bounds = [oPathCopy bounds]; 2859 wi = conRect.size.width = bounds.size.width + 4*Abs(w); 2860 h = conRect.size.height = bounds.size.height + 4*Abs(w); /* need a little space for our contour */ 2861 2862 /* need a minimum scale of */ 2863 scale = s = 1.0; 2864 conRect.size.width = wi*scale; conRect.size.height = h*scale; /* last guilty values */ 2865 bytes = (wi*scale) * (h*scale); 2866 w2 = Abs(w)*scale/2.0; 2867 2868 while ( bytes < maxBytes && s < 50 /*&& conRect.size.width < 10000 && conRect.size.height < 10000*/ ) 2869 { 2870 scale = s; 2871 w2 = Abs(w)*scale/2.0; 2872 conRect.size.width = wi*scale; conRect.size.height = h*scale; /* last guilty values */ 2873 if ( (quality == 2 && w2 > 40) || (quality == 1 && w2 > 30) || (!quality && w2 > 20) ) // 20 2874 break; /* stop scale is great enough */ 2875 2876 s += 1.0; 2877 bytes = (wi*s) * (h*s); // 1 byte is one pixel; 2878 if ( wi*s > 10000 || h*s > 10000 ) 2879 break; // too big !!! 2880 } 2881 if ( conRect.size.width > 10000 || conRect.size.height > 10000 ) // good bye 2882 { [oPathCopy release]; return path; } 2883 2884 /* need our half width/minWidth in pixel and scaled */ 2885 if ( (w2-((int)w2)) > 0.5 ) 2886 { w2Int = w2 + 1; 2887 conRect.size.width += 6.0; conRect.size.height += 6.0; 2888 } 2889 else 2890 { w2Int = w2; 2891 conRect.size.width += 4.0; conRect.size.height += 4.0; 2892 } 2893 conRect.origin.x = conRect.origin.y = 10.0; 2894 2895 /* scale oPathCopy */ 2896 center.x = bounds.origin.x + bounds.size.width/2.0; 2897 center.y = bounds.origin.y + bounds.size.height/2.0; 2898 [oPathCopy scale:scale :scale withCenter:center]; 2899 bounds = [oPathCopy bounds]; 2900 2901 /* move oPathCopy to ~0 */ 2902 moveP.x = -(bounds.origin.x - 4*w2Int - 2.0); 2903 moveP.y = -(bounds.origin.y - 4*w2Int - 2.0); 2904 [oPathCopy moveBy:moveP]; 2905 2906 /* build an offscreen window 2907 * in which we draw the scaled black copy of original path on white background NSBackingStoreBuffered NSBackingStoreRetained 2908 */ 2909 win = [[NSWindow alloc] initWithContentRect:conRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreRetained defer:NO]; 2910 [win setDynamicDepthLimit:NO]; 2911 [win setDepthLimit:NSBestDepth(NSCalibratedWhiteColorSpace, 8, 8, YES, NULL)]; 2912//[win setDepthLimit:NSBestDepth(NSCalibratedRGBColorSpace, 8, 24, NO, NULL)]; // test apple 2913 2914 [win setBackgroundColor:( w < 0 ) ? [NSColor grayColor] : [NSColor blackColor]]; 2915#if DEBUG_CONTUR 2916[win makeKeyAndOrderFront:self]; /* weglassen wenn nicht gesehen werden soll */ 2917#endif 2918 conView = [win contentView]; 2919 [conView display]; 2920 2921 /* now draw our white scaled path in view 2922 */ 2923 [conView lockFocus]; 2924 2925#ifdef __APPLE__ 2926[[NSGraphicsContext currentContext] setShouldAntialias:NO]; 2927#endif 2928 2929 [oPathCopy setFillColor:( w > 0 ) ? [NSColor grayColor] : nxWhite]; 2930 [oPathCopy drawWithPrincipal:nil]; 2931 2932 // w < 0 -> contour inside path 2933 // w > 0 -> contour outside path 2934 // w == 0 -> white filled black Background 2935 if (w) 2936 { 2937 [oPathCopy setColor:(w < 0) ? nxBlack : nxWhite]; 2938 [oPathCopy setFilled:NO]; 2939 [oPathCopy setWidth:w2Int*2.0]; 2940 [oPathCopy drawWithPrincipal:nil]; 2941 } 2942 /* force 8 bit gray -> we must draw one thing gray */ 2943 { VRectangle *r=[VRectangle rectangle]; 2944 2945 [r setVertices:NSMakePoint(1.0,1.0) :NSMakePoint(1.0,1.0)]; 2946 [r setFillColor:[NSColor grayColor]]; 2947 [r setFilled:YES]; 2948 [r drawWithPrincipal:nil]; 2949 } 2950 /* get pixel information into data (char string) */ 2951 rect.origin = NSZeroPoint; 2952 right = rect.size.width = (int)(conRect.size.width); /* our with scale and bounds calculated width */ 2953 height = rect.size.height = (int)(conRect.size.height); 2954 2955//[[NSColor redColor] set]; // test apple 2956//NSRectFill(NSMakeRect(1, 1, 1, 1)); 2957 2958 bitmapImage = [[NSBitmapImageRep allocWithZone:[self zone]] initWithFocusedViewRect:rect]; 2959 2960 // apple 2961 if ([bitmapImage bitsPerPixel] > 8 || ![bitmapImage isPlanar] || [bitmapImage samplesPerPixel] > 1) 2962 { NSBitmapImageRep *abitmap; 2963 2964 if ([bitmapImage bitsPerSample] == 8) // meshed 2965 { int ny, width; 2966 int bpr = [bitmapImage bytesPerRow], spp = 1, abpr; 2967 int bpp = [bitmapImage bytesPerPlane]; 2968 unsigned char *planes[5]; 2969 2970 abitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL 2971 pixelsWide:rect.size.width 2972 pixelsHigh:rect.size.height 2973 bitsPerSample:8 2974 samplesPerPixel:1 2975 hasAlpha:NO isPlanar:YES 2976 colorSpaceName:NSCalibratedWhiteColorSpace 2977 bytesPerRow:rect.size.width 2978 bitsPerPixel:8]; 2979 2980 data = [abitmap bitmapData]; 2981 abpr = [abitmap bytesPerRow]; 2982 [bitmapImage getBitmapDataPlanes:planes]; 2983 2984 if (![bitmapImage isPlanar]) 2985 spp = [bitmapImage bitsPerPixel]/8; 2986 width = bpr / spp; // bytesPerRow / samplesPerPixel 2987 for (y=0, ny=0; y<bpp; y+=bpr, ny+=abpr) 2988 { 2989 for (x=0; x<width; x++) 2990 { 2991 *((LONG*)(data+ny+x)) = *((LONG*)(planes[0]+y+x*spp)); 2992 } 2993 } 2994 } 2995 else 2996 { [conView unlockFocus]; 2997 [win close]; 2998 [bitmapImage release]; 2999 [oPathCopy release]; 3000 return path; 3001 } 3002 [bitmapImage release]; 3003 bitmapImage = abitmap; 3004 } 3005 size = [bitmapImage bytesPerPlane]; 3006 data = [bitmapImage bitmapData]; 3007 bytesPerRow = [bitmapImage bytesPerRow]; 3008 bytesPerRowHalf = bytesPerRow/2.0; 3009 { int lineArray[bytesPerRowHalf], lineCnt = 0; 3010 NSPoint *pts; 3011 pts = malloc(right * sizeof(NSPoint)); 3012 3013 /* set loop parameters */ 3014 right -= (2*w2Int+1); 3015 height -= (2*w2Int+1); 3016 3017#if DEBUG_CONTUR 3018[nxGray set]; 3019#endif 3020 3021 /* vectorize contour */ 3022 start = 2*w2Int+1; 3023 for (y=start; y<height; y++) 3024 { int pCnt=0, byteY, byteX; 3025 3026 byteY = y * bytesPerRow; /* the height */ 3027 byteY = size - byteY - bytesPerRow; 3028 for (x=start; x<right && byteY+x+19 < size; x++) 3029 { 3030 byteX = byteY+x; 3031 if ( *((LONG*)(data+byteX)) == black ) 3032 { if ( *((LONG*)(data+byteX+4)) == black ) 3033 { if ( *((LONG*)(data+byteX+8)) == black ) 3034 { if ( *((LONG*)(data+byteX+12)) == black ) 3035 { if ( *((LONG*)(data+byteX+16)) == black ) 3036 { x += 16; continue; } 3037 else { x += 12; continue; } 3038 } 3039 else { x += 8; continue; } 3040 } 3041 else { x += 4; continue; } 3042 } 3043 else { continue; } 3044 } 3045 else if ( *((LONG*)(data+byteX-bytesPerRow-1)) == -1 && *((LONG*)(data+byteX-1)) == -1 && 3046 *((LONG*)(data+byteX+bytesPerRow-1)) == -1 ) 3047 { 3048 if ( *((LONG*)(data+byteX-bytesPerRow+3)) == -1 && *((LONG*)(data+byteX+3)) == -1 && 3049 *((LONG*)(data+byteX+bytesPerRow+3)) == -1 ) 3050 { 3051 if ( *((LONG*)(data+byteX-bytesPerRow+7)) == -1 && *((LONG*)(data+byteX+7)) == -1 && 3052 *((LONG*)(data+byteX+bytesPerRow+7)) == -1 ) 3053 { 3054 if ( *((LONG*)(data+byteX-bytesPerRow+11)) == -1 && *((LONG*)(data+byteX+11)) == -1 && 3055 *((LONG*)(data+byteX+bytesPerRow+11)) == -1 ) 3056 { 3057 if ( *((LONG*)(data+byteX-bytesPerRow+15)) == -1 && *((LONG*)(data+byteX+15)) == -1 && 3058 *((LONG*)(data+byteX+bytesPerRow+15)) == -1 ) 3059 { 3060 if ( *((LONG*)(data+byteX-bytesPerRow+19)) == -1 && *((LONG*)(data+byteX+19)) == -1 && 3061 *((LONG*)(data+byteX+bytesPerRow+19)) == -1 ) 3062 { x += 19; continue; } 3063 else { x += 15; continue; } 3064 } 3065 else { x += 11; continue; } 3066 } 3067 else { x += 7; continue; } 3068 } 3069 else { x += 3; continue; } 3070 } 3071 else { continue; } 3072 } 3073 if ( *(data+byteX) != white ) 3074 continue; 3075 /* l d r u is a black pixel -> one of our pixels */ 3076 if ( *(data+byteX-1) == black || *(data+byteX+bytesPerRow) == black || 3077 *(data+byteX+1) == black || *(data+byteX-bytesPerRow) == black ) 3078 { NSPoint nxp = {x, y}; 3079 pts[pCnt] = nxp; 3080 pCnt++; 3081//#if DEBUG_CONTUR 3082//NSRectFill(NSMakeRect(x, y, 1, 1)); 3083//#endif 3084 } 3085 } 3086 if ( pCnt ) 3087 [self buildPath:path :pts :pCnt :w :lineArray :&lineCnt]; 3088 } 3089 free(pts); 3090 } // lineArray, lineCnt 3091#if DEBUG_CONTUR 3092printf("%s Hour.Min.Sec vor Optimieren\n", [[[NSCalendarDate date] descriptionWithCalendarFormat:@"%H.%M.%S"] cString]); 3093#endif 3094 3095 /* correct path */ 3096 /*if ( [[path list] count] ) 3097 { for (x=(int)[[path list] count]-1; x>=0; x--) 3098 { VGraphic *lineG = [[path list] objectAtIndex:x]; // nach opt - nur singles ! 3099 NSPoint start, end; 3100 [(VLine*)lineG getVertices:&start :&end]; 3101 if ( //(![lineG isSelected] && Diff(start.x, end.x) <= 2 && Diff(start.y, end.y) <= 2) || 3102 (Diff(start.x, end.x) <= 1 && Diff(start.y, end.y) <= 1) ) 3103 [[path list] removeObjectAtIndex:x]; 3104 } 3105 }*/ 3106 [self optimizePath:path :w2Int]; 3107 3108 /* move and scale path to old great */ 3109 moveP.x = -moveP.x; moveP.y = -moveP.y; 3110 [path moveBy:moveP]; 3111 scale = 1/scale; 3112 [path scale:scale :scale withCenter:center]; 3113 3114 3115#if 0 3116{ int i; 3117 NSPoint s, e; 3118 3119 printf("VPath\n"); 3120 for (i=0; i<[[path list] count]; i++) 3121 { Line *l1=[[path list] objectAtIndex:i]; 3122 3123 [l1 getVertices:&s :&e]; 3124 printf("%.2f s.x\t %.2f s.y\t %.2f e.x\t %.2f e.y\n", s.x, s.y, e.x, e.y); 3125 } 3126 printf("\n3DLinePath\n"); 3127 for (i=0; i<[[linePath list] count]; i++) 3128 { VLine3D *l1=[[linePath list] objectAtIndex:i]; 3129 3130 [l1 getVertices:&s :&e]; 3131 printf("%.2f s.x\t %.2f s.y\t %.2f e.x\t %.2f e.y\n", s.x, s.y, e.x, e.y); 3132 } 3133} 3134#endif 3135 [conView unlockFocus]; 3136 [win close]; 3137 [bitmapImage release]; 3138 [oPathCopy release]; 3139#if DEBUG_CONTUR 3140printf("%s Hour.Min.Sec End\n\n", [[[NSCalendarDate date] descriptionWithCalendarFormat:@"%H.%M.%S"] cString]); 3141#endif 3142 [path setDirectionCCW:[oPath isDirectionCCW]]; 3143 return path; 3144} 3145 3146- (VPath*)contourImage:(VImage*)image width:(float)width 3147{ VPath *path; 3148 NSRect conRect, bounds, rect; 3149 NSSize imageSize; 3150 id win, conView; 3151 float w=width, w2, scaleX = 1, scaleY = 1; 3152 int x, y, right, height, start, w2Int, bytesPerRowHalf; 3153 NSColor *nxBlack; 3154 NSPoint moveP, center; 3155 NSBitmapImageRep *bitmapImage; 3156 unsigned char color, *data2; 3157#if DEBUG_CONTUR 3158 NSColor *nxGray, *nxWhite; 3159 nxGray = [NSColor colorWithCalibratedRed:0.335 green:0.335 blue:0.335 alpha:1.0]; 3160 nxWhite = [NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0]; 3161 printf("%s Hour.Min.Sec Start\n", [[[NSCalendarDate date] descriptionWithCalendarFormat:@"%H.%M.%S"] cString]); 3162#endif 3163 3164 nxBlack = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 3165 3166 path = [VPath path]; 3167 [path setColor:nxBlack]; 3168 [path setFilled:NO]; 3169 [path setWidth:0]; 3170 [path setSelected:NO]; 3171 3172// if ( !w ) 3173// return path; 3174 3175 /* get bouns of image size and original size */ 3176 bounds.size = [image originalSize]; 3177 bounds.origin = [image origin]; 3178 3179 imageSize = [image size]; 3180 scaleX = bounds.size.width/imageSize.width; 3181 scaleY = bounds.size.height/imageSize.height; 3182 3183 /* need our half width/minWidth in pixel and scaled */ 3184 ( scaleX < scaleY ) ? (w2 = Abs(w)*scaleX/2.0) : (w2 = Abs(w)*scaleY/2.0); 3185 3186 ( (w2-((int)w2)) > 0.5 ) ? (w2Int = w2 + 1) : (w2Int = w2); 3187// if ( !w2Int ) w2Int = 1; 3188 3189 if ( w2Int > 46 ) // must scale origninalSize -> to hold the Verhaeltnisse 3190 { 3191 while ( w2Int > 46 ) 3192 { 3193 scaleX -= 1.0; scaleY -= 1.0; 3194 ( scaleX < scaleY ) ? (w2 = Abs(w)*scaleX/2.0) : (w2 = Abs(w)*scaleY/2.0); 3195 ( (w2-((int)w2)) > 0.5 ) ? (w2Int = w2 + 1) : (w2Int = w2); 3196 } 3197 bounds.size.width = imageSize.width*scaleX; 3198 bounds.size.height = imageSize.height*scaleY; 3199 } 3200 conRect.size.width = bounds.size.width + 2*w2Int + 20; 3201 conRect.size.height = bounds.size.height + 2*w2Int + 20; /* need a little space for our contour */ 3202 conRect.origin.x = conRect.origin.y = w2Int+10.0; 3203 3204 if ( conRect.size.width > 10000 || conRect.size.height > 10000 ) // good bye 3205 return path; 3206 3207 /* build an offscreen window 3208 * in which we draw the scaled black copy of original path on white background NSBackingStoreBuffered NSBackingStoreRetained 3209 */ 3210 win = [[NSWindow alloc] initWithContentRect:conRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreRetained defer:NO]; 3211 [win setDynamicDepthLimit:NO]; 3212 [win setDepthLimit:NSBestDepth(NSCalibratedWhiteColorSpace, 8, 8, YES, NULL)]; 3213 3214 [win setBackgroundColor:[NSColor whiteColor]]; 3215#if DEBUG_CONTUR 3216[win makeKeyAndOrderFront:self]; /* weglassen wenn nicht gesehen werden soll */ 3217#endif 3218 conView = [win contentView]; 3219 [conView display]; 3220 3221 /* get copy of image */ 3222 [[image image] setSize:bounds.size]; 3223 3224 /* now draw our black scaled path in view 3225 */ 3226 [conView lockFocus]; 3227#ifdef __APPLE__ 3228[[NSGraphicsContext currentContext] setShouldAntialias:NO]; 3229#endif 3230 [[image image] compositeToPoint:conRect.origin operation:NSCompositeSourceOver]; // NSCompositeCopy 3231 3232 /* get pixel information into data (char string) */ 3233 rect.origin = NSZeroPoint; 3234 right = rect.size.width = (int)(conRect.size.width); /* our with scale and bounds calculated width */ 3235 height = rect.size.height = (int)(conRect.size.height); 3236 3237 [[NSColor grayColor] set]; NSRectFill(NSMakeRect(2, 2, 1, 1)); // hack to force 8 bit gray bitmap 3238 bitmapImage = [[NSBitmapImageRep allocWithZone:[self zone]] initWithFocusedViewRect:rect]; 3239 // apple 3240 if ([bitmapImage bitsPerPixel] > 8 || ![bitmapImage isPlanar] || [bitmapImage samplesPerPixel] > 1) 3241 { NSBitmapImageRep *abitmap; 3242 3243 if ([bitmapImage bitsPerSample] == 8) // meshed 3244 { int ny, width; 3245 int bpr = [bitmapImage bytesPerRow], spp = 1, abpr; 3246 int bpp = [bitmapImage bytesPerPlane]; 3247 unsigned char *planes[5]; 3248 3249 abitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL 3250 pixelsWide:rect.size.width 3251 pixelsHigh:rect.size.height 3252 bitsPerSample:8 3253 samplesPerPixel:1 3254 hasAlpha:NO isPlanar:YES 3255 colorSpaceName:NSCalibratedWhiteColorSpace 3256 bytesPerRow:rect.size.width 3257 bitsPerPixel:8]; 3258 3259 data = [abitmap bitmapData]; 3260 abpr = [abitmap bytesPerRow]; 3261 [bitmapImage getBitmapDataPlanes:planes]; 3262 3263 if (![bitmapImage isPlanar]) 3264 spp = [bitmapImage bitsPerPixel]/8; 3265 width = bpr / spp; // bytesPerRow / samplesPerPixel 3266 for (y=0, ny=0; y<bpp; y+=bpr, ny+=abpr) 3267 { 3268 for (x=0; x<width; x++) 3269 { 3270 *((LONG*)(data+ny+x)) = *((LONG*)(planes[0]+y+x*spp)); 3271 } 3272 } 3273 } 3274 else 3275 { [conView unlockFocus]; 3276 [win close]; 3277 [bitmapImage release]; 3278 return path; 3279 } 3280 [bitmapImage release]; 3281 bitmapImage = abitmap; 3282 } 3283 size = [bitmapImage bytesPerPlane]; 3284 data = [bitmapImage bitmapData]; 3285 bytesPerRow = [bitmapImage bytesPerRow]; 3286 3287 /* set loop parameters */ 3288 right -= 10.0; 3289 height -= 10.0; 3290 3291#if DEBUG_CONTUR 3292[nxBlack set]; 3293#endif 3294 3295 // set not white bytes to black !!!!!!!!!! 3296 start = 10.0; // (gdb) x/100tb data 3297 for (y=start; y<height; y++) 3298 { int byteY, byteX; 3299 3300 byteY = size - (y * bytesPerRow) - bytesPerRow; /* the height */ 3301 3302 for (x=start; x<right && byteY+x+19 < size; x++) 3303 { 3304 byteX = byteY+x; 3305 if ( *((LONG*)(data+byteX)) == -1 ) 3306 { if ( *((LONG*)(data+byteX+4)) == -1 ) 3307 { if ( *((LONG*)(data+byteX+8)) == -1 ) 3308 { if ( *((LONG*)(data+byteX+12)) == -1 ) 3309 { if ( *((LONG*)(data+byteX+16)) == -1 ) 3310 { x += 16; continue; } 3311 else { x += 12; continue; } 3312 } 3313 else { x += 8; continue; } 3314 } 3315 else { x += 4; continue; } 3316 } 3317 else { continue; } 3318 } 3319 else if ( *((LONG*)(data+byteX-bytesPerRow-1)) == black && *((LONG*)(data+byteX-1)) == black && 3320 *((LONG*)(data+byteX+bytesPerRow-1)) == black ) 3321 { 3322 if ( *((LONG*)(data+byteX-bytesPerRow+3)) == black && *((LONG*)(data+byteX+3)) == black && 3323 *((LONG*)(data+byteX+bytesPerRow+3)) == black ) 3324 { 3325 if ( *((LONG*)(data+byteX-bytesPerRow+7)) == black && *((LONG*)(data+byteX+7)) == black && 3326 *((LONG*)(data+byteX+bytesPerRow+7)) == black ) 3327 { 3328 if ( *((LONG*)(data+byteX-bytesPerRow+11)) == black && *((LONG*)(data+byteX+11)) == black && 3329 *((LONG*)(data+byteX+bytesPerRow+11)) == black ) 3330 { 3331 if ( *((LONG*)(data+byteX-bytesPerRow+15)) == black && *((LONG*)(data+byteX+15)) == black && 3332 *((LONG*)(data+byteX+bytesPerRow+15)) == black ) 3333 { 3334 if ( *((LONG*)(data+byteX-bytesPerRow+19)) == black && *((LONG*)(data+byteX+19)) == black 3335 && *((LONG*)(data+byteX+bytesPerRow+19)) == black ) 3336 { x += 19; continue; } 3337 else { x += 15; continue; } 3338 } 3339 else { x += 11; continue; } 3340 } 3341 else { x += 7; continue; } 3342 } 3343 else { x += 3; continue; } 3344 } 3345 else { continue; } 3346 } 3347 if ( *(data+byteX) != white ) 3348 { 3349 if ( *(data+byteX) >= whiteStop ) 3350 *(data+byteX) = white; // the color does nt matter 3351 else 3352 *(data+byteX) = black; // the color does nt matter 3353#if DEBUG_CONTUR 3354//NSRectFill(NSMakeRect(x, y, 1, 1)); 3355#endif 3356 } 3357 } 3358 } 3359 // w < 0 -> contour inside path 3360 // w > 0 -> contour outside path 3361// ( w < 0 ) ? (color = black) : (color = white); 3362 ( w < 0 ) ? (color = white) : (color = black); 3363 3364 data2 = malloc(size * sizeof(unsigned char)); 3365 data2 = memcpy(data2, data, size); // copy !! allways the same !!! 3366 3367#if DEBUG_CONTUR 3368if ( w < 0 ) [nxWhite set]; else [nxBlack set]; 3369[nxGray set]; 3370#endif 3371 start = 10.0; // (gdb) x/100tb data 3372 for (y=start; y<height && w2Int; y++) 3373 { int byteY, byteX; 3374 3375 byteY = size - (y * bytesPerRow) - bytesPerRow; /* the height */ 3376 3377 for (x=start; x<right && byteY+x+19 < size; x++) 3378 { 3379 byteX = byteY+x; 3380 if ( *((LONG*)(data2+byteX)) == -1 ) 3381 { if ( *((LONG*)(data2+byteX+4)) == -1 ) 3382 { if ( *((LONG*)(data2+byteX+8)) == -1 ) 3383 { if ( *((LONG*)(data2+byteX+12)) == -1 ) 3384 { if ( *((LONG*)(data2+byteX+16)) == -1 ) 3385 { x += 16; continue; } 3386 else { x += 12; continue; } 3387 } 3388 else { x += 8; continue; } 3389 } 3390 else { x += 4; continue; } 3391 } 3392 else { continue; } 3393 } 3394//#if 0 3395 else if ( *((LONG*)(data2+byteX-bytesPerRow-1)) == black && *((LONG*)(data2+byteX-1)) == black && 3396 *((LONG*)(data2+byteX+bytesPerRow-1)) == black ) 3397 { 3398 if ( *((LONG*)(data2+byteX-bytesPerRow+3)) == black && *((LONG*)(data2+byteX+3)) == black && 3399 *((LONG*)(data2+byteX+bytesPerRow+3)) == black ) 3400 { 3401 if ( *((LONG*)(data2+byteX-bytesPerRow+7)) == black && *((LONG*)(data2+byteX+7)) == black && 3402 *((LONG*)(data2+byteX+bytesPerRow+7)) == black ) 3403 { 3404 if ( *((LONG*)(data2+byteX-bytesPerRow+11)) == black && *((LONG*)(data2+byteX+11)) == black && 3405 *((LONG*)(data2+byteX+bytesPerRow+11)) == black ) 3406 { 3407 if ( *((LONG*)(data2+byteX-bytesPerRow+15)) == black && *((LONG*)(data2+byteX+15)) == black && 3408 *((LONG*)(data2+byteX+bytesPerRow+15)) == black ) 3409 { 3410 if ( *((LONG*)(data2+byteX-bytesPerRow+19)) == black && *((LONG*)(data2+byteX+19)) == black 3411 && *((LONG*)(data2+byteX+bytesPerRow+19)) == black ) 3412 { x += 19; continue; } 3413 else { x += 15; continue; } 3414 } 3415 else { x += 11; continue; } 3416 } 3417 else { x += 7; continue; } 3418 } 3419 else { x += 3; continue; } 3420 } 3421 else { continue; } 3422 } 3423//#endif 3424 if ( *(data2+byteX) == white ) 3425 continue; 3426 /* l d r u is a black pixel -> one of our pixels */ 3427 if ( *(data2+byteX-1) == white || *(data2+byteX+bytesPerRow) == white || 3428 *(data2+byteX+1) == white || *(data2+byteX-bytesPerRow) == white ) 3429 { 3430 [self drawArcInDataAt:(byteY+x) radius:w2Int color:color]; 3431#if DEBUG_CONTUR 3432PSarc(x, y, w2Int, 0.0, 360.0); PSfill(); 3433#endif 3434 } 3435 } 3436 } 3437 free(data2); 3438 3439 [self invertData]; 3440 3441 bytesPerRowHalf = bytesPerRow/2.0; 3442 { int lineArray[bytesPerRowHalf], lineCnt = 0; 3443 NSPoint *pts; 3444 pts = malloc(right * sizeof(NSPoint)); 3445 3446#if DEBUG_CONTUR 3447[nxBlack set]; 3448#endif 3449 /* vectorize contour */ 3450 start = 10.0; 3451 for (y=start; y<height; y++) 3452 { int pCnt=0, byteY, byteX; 3453 3454 byteY = y * bytesPerRow; /* the height */ 3455 byteY = size - byteY - bytesPerRow; 3456 for (x=start; x<right; x++) 3457 { 3458 byteX = byteY+x; 3459 if ( *((LONG*)(data+byteX)) == black ) 3460 { if ( *((LONG*)(data+byteX+4)) == black ) 3461 { if ( *((LONG*)(data+byteX+8)) == black ) 3462 { if ( *((LONG*)(data+byteX+12)) == black ) 3463 { if ( *((LONG*)(data+byteX+16)) == black ) 3464 { x += 16; continue; } 3465 else { x += 12; continue; } 3466 } 3467 else { x += 8; continue; } 3468 } 3469 else { x += 4; continue; } 3470 } 3471 else { continue; } 3472 } 3473 else if ( *((LONG*)(data+byteX-bytesPerRow-1)) == -1 && *((LONG*)(data+byteX-1)) == -1 && 3474 *((LONG*)(data+byteX+bytesPerRow-1)) == -1 ) 3475 { 3476 if ( *((LONG*)(data+byteX-bytesPerRow+3)) == -1 && *((LONG*)(data+byteX+3)) == -1 && 3477 *((LONG*)(data+byteX+bytesPerRow+3)) == -1 ) 3478 { 3479 if ( *((LONG*)(data+byteX-bytesPerRow+7)) == -1 && *((LONG*)(data+byteX+7)) == -1 && 3480 *((LONG*)(data+byteX+bytesPerRow+7)) == -1 ) 3481 { 3482 if ( *((LONG*)(data+byteX-bytesPerRow+11)) == -1 && *((LONG*)(data+byteX+11)) == -1 && 3483 *((LONG*)(data+byteX+bytesPerRow+11)) == -1 ) 3484 { 3485 if ( *((LONG*)(data+byteX-bytesPerRow+15)) == -1 && *((LONG*)(data+byteX+15)) == -1 && 3486 *((LONG*)(data+byteX+bytesPerRow+15)) == -1 ) 3487 { 3488 if ( *((LONG*)(data+byteX-bytesPerRow+19)) == -1 && *((LONG*)(data+byteX+19)) == -1 && 3489 *((LONG*)(data+byteX+bytesPerRow+19)) == -1 ) 3490 { x += 19; continue; } 3491 else { x += 15; continue; } 3492 } 3493 else { x += 11; continue; } 3494 } 3495 else { x += 7; continue; } 3496 } 3497 else { x += 3; continue; } 3498 } 3499 else { continue; } 3500 } 3501 if ( *(data+byteX) != white ) 3502 continue; 3503 /* l d r u is a black pixel -> one of our pixels */ 3504 if ( *(data+byteX-1) == black || *(data+byteX+bytesPerRow) == black || 3505 *(data+byteX+1) == black || *(data+byteX-bytesPerRow) == black ) 3506 { NSPoint nxp = {x, y}; 3507 pts[pCnt] = nxp; 3508 pCnt++; 3509#if DEBUG_CONTUR 3510//NSRectFill(NSMakeRect(x, y, 1, 1)); 3511#endif 3512 } 3513 } 3514 if ( pCnt ) 3515 [self buildPath:path :pts :pCnt :w :lineArray :&lineCnt]; 3516 } 3517 free(pts); 3518 } // lineArray, lineCnt 3519#if DEBUG_CONTUR 3520printf("%s Hour.Min.Sec vor Optimieren\n", [[[NSCalendarDate date] descriptionWithCalendarFormat:@"%H.%M.%S"] cString]); 3521#endif 3522 3523 [self optimizePath:path :w2Int]; 3524 3525 /* move and scale path to old greatness */ 3526 /* move and scale path and linePath and *fillPath to old great */ 3527 moveP.x = -(bounds.origin.x - w2Int - 9.0); // dont know why 9.0 insteat 10.0 is correct - but it is 3528 moveP.y = -(bounds.origin.y - w2Int - 9.0); // w2Int+10.0 -> think: lower left coner of image is IN/AT composite pt 3529 moveP.x = -moveP.x; moveP.y = -moveP.y; 3530 3531 center = bounds.origin; 3532 scaleX = 1.0/scaleX; 3533 scaleY = 1.0/scaleY; 3534 [path moveBy:moveP]; 3535 [path scale:scaleX :scaleY withCenter:center]; 3536 3537 [conView unlockFocus]; 3538 [win close]; 3539 [[image image] setSize:imageSize]; // set to old great 3540 [bitmapImage release]; 3541#if DEBUG_CONTUR 3542printf("%s Hour.Min.Sec End\n\n", [[[NSCalendarDate date] descriptionWithCalendarFormat:@"%H.%M.%S"] cString]); 3543#endif 3544 return path; 3545} 3546 3547/* modified: 23.02.05 3548 * get contour of list using a bitmap algorithm 3549 * return the calculated path 3550 */ 3551- (VPath*)contourList:(NSArray*)oList width:(float)width 3552{ VPath *path; 3553 NSRect conRect, bounds=NSZeroRect, rect; 3554 id win, conView; 3555 float w=width, w2, bytes, scale = 1, maxBytes = 110250000, wi, h, s, maxW=0; 3556 int i, x, y, right, height, start, w2Int, bytesPerRowHalf, quality = 2; 3557 int cnt = [oList count], drawed = 0; 3558 NSColor *nxWhite, *nxBlack; 3559 NSPoint moveP, center; 3560 NSBitmapImageRep *bitmapImage; 3561 3562#if DEBUG_CONTUR 3563 NSColor *nxGray; 3564 nxGray = [NSColor colorWithCalibratedRed:0.335 green:0.335 blue:0.335 alpha:1.0]; 3565printf("%s Hour.Min.Sec Start\n", [[[NSCalendarDate date] descriptionWithCalendarFormat:@"%H.%M.%S"] cString]); 3566#endif 3567 3568 if (!cnt) 3569 return nil; 3570 3571 nxBlack = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 3572 nxWhite = [NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0]; 3573 3574 path = [VPath path]; 3575 [path setColor:[[oList objectAtIndex:0] color]]; 3576 [path setFilled:NO]; 3577 [path setWidth:0]; 3578 [path setSelected:NO]; 3579 3580 /* get Bounds and maxW */ 3581 for (i=0; i < cnt; i++) 3582 { VGraphic *g = [oList objectAtIndex:i]; 3583 3584 if ([g isKindOfClass:[VGroup class]]) 3585 { int j, gCnt = [(VGroup*)g countRecursive]; 3586 3587 for (j=0; j<gCnt; j++) 3588 { VGraphic *gg = [(VGroup*)g recursiveObjectAtIndex:j]; 3589 3590 if ( [gg width] > maxW ) 3591 maxW = [gg width]; 3592 rect = [gg bounds]; 3593 bounds = (!bounds.size.width) ? rect : NSUnionRect(rect, bounds); 3594 } 3595 } 3596 else 3597 { if ( [g width] > maxW ) 3598 maxW = [g width]; 3599 rect = [g bounds]; 3600 bounds = (!bounds.size.width) ? rect : NSUnionRect(rect, bounds); 3601 } 3602 } 3603 /* calc content rect size / scale factor 3604 * to get not more than 20 MB memory 3605 * the bounds of the path: width*height / 8(bit) * 2(color deepnes) 3606 */ 3607 3608// (Abs(w)+maxW) ++ maxWidth of objects from list !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 3609 wi = conRect.size.width = bounds.size.width + 4*Abs(w+maxW); 3610 h = conRect.size.height = bounds.size.height + 4*Abs(w+maxW); /* need a little space for our contour */ 3611 3612 /* need a minimum scale of */ 3613 scale = s = 1.0; 3614 conRect.size.width = wi*scale; conRect.size.height = h*scale; /* last guilty values */ 3615 bytes = (wi*scale) * (h*scale); 3616 w2 = Abs(w)*scale/2.0; 3617 3618 while ( bytes < maxBytes && s < 50 /*&& conRect.size.width < 10000 && conRect.size.height < 10000*/ ) // 8000 3619 { 3620 scale = s; 3621 w2 = Abs(w)*scale/2.0; 3622 conRect.size.width = wi*scale; conRect.size.height = h*scale; /* last guilty values */ 3623 if ( (quality == 2 && w2 > 40) || (quality == 1 && w2 > 30) || (!quality && w2 > 20) ) // 20 3624 break; /* stop scale is great enough */ 3625 3626 s += 1.0; 3627 bytes = (wi*s) * (h*s); // 1 byte is one pixel; 3628 if ( wi*s > 10000 || h*s > 10000 ) // > 10000 3629 break; // too big !!! 3630 } 3631 if ( conRect.size.width > 10000 || conRect.size.height > 10000 ) // good bye > 10000 3632 return nil; 3633 3634 w2 = Abs(w+maxW)*scale/2.0; 3635 /* need our half width/minWidth in pixel and scaled */ 3636 if ( (w2-((int)w2)) > 0.5 ) 3637 { w2Int = w2 + 1; 3638 conRect.size.width += 6.0; conRect.size.height += 6.0; 3639 } 3640 else 3641 { w2Int = w2; 3642 conRect.size.width += 4.0; conRect.size.height += 4.0; 3643 } 3644 conRect.origin.x = conRect.origin.y = 10.0; 3645 3646 /* center */ 3647 center.x = bounds.origin.x + bounds.size.width/2.0; 3648 center.y = bounds.origin.y + bounds.size.height/2.0; 3649 3650 bounds = NSZeroRect; 3651 for (i=0; i < cnt; i++) 3652 { id g = [oList objectAtIndex:i]; 3653 3654 [g scale:scale :scale withCenter:center]; 3655 rect = [g bounds]; 3656 bounds = (!bounds.size.width) ? rect : NSUnionRect(rect, bounds); 3657 } 3658 3659 /* move oList to ~0 */ 3660 moveP.x = -(bounds.origin.x - 4*w2Int - 2.0); 3661 moveP.y = -(bounds.origin.y - 4*w2Int - 2.0); 3662 3663 for (i=0; i < cnt; i++) 3664 [[oList objectAtIndex:i] moveBy:moveP]; 3665 3666 /* build an offscreen window 3667 * in which we draw the scaled black copy of original path on white background NSBackingStoreBuffered NSBackingStoreRetained 3668 */ 3669 win = [[NSWindow alloc] initWithContentRect:conRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreRetained defer:NO]; 3670 [win setDynamicDepthLimit:NO]; 3671 [win setDepthLimit:NSBestDepth(NSCalibratedWhiteColorSpace, 8, 8, YES, NULL)]; 3672//[win setDepthLimit:NSBestDepth(NSCalibratedRGBColorSpace, 8, 24, NO, NULL)]; // test apple 3673 3674// [win setBackgroundColor:( w < 0 ) ? [NSColor grayColor] : [NSColor blackColor]]; 3675 [win setBackgroundColor:[NSColor blackColor]]; 3676 3677#if DEBUG_CONTUR 3678[win makeKeyAndOrderFront:self]; /* weglassen wenn nicht gesehen werden soll */ 3679#endif 3680 conView = [win contentView]; 3681 [conView display]; 3682 3683 /* now draw our scaled path in view 3684 */ 3685 [conView lockFocus]; 3686 3687#ifdef __APPLE__ 3688[[NSGraphicsContext currentContext] setShouldAntialias:NO]; 3689#endif 3690 3691 for (i=0; i < cnt; i++) 3692 { VGraphic *g = [oList objectAtIndex:i]; 3693 float gWidth = ([g width]/scale), endW = w + gWidth, oldGWidth = [g width]; 3694 int gFilled = [g filled]; 3695 3696 if ([g isKindOfClass:[VGroup class]]) 3697 { int j, gCnt = [(VGroup*)g countRecursive]; 3698 3699 for (j=0; j<gCnt; j++) 3700 { VGraphic *gg = [(VGroup*)g recursiveObjectAtIndex:j]; 3701 NSColor *fillColor = nil, *color = [[gg color] retain]; 3702 3703 gWidth = ([gg width]/scale); 3704 endW = w + gWidth; 3705 gFilled = oldGWidth = [gg filled]; 3706 3707 if ( [gg respondsToSelector:@selector(setFillColor:)] ) 3708 fillColor = [[(VPath*)gg fillColor] retain]; 3709 3710 /* need our half width/minWidth in pixel and scaled */ 3711 w2 = Abs(w+gWidth)*scale/2.0; 3712 if ([gg isKindOfClass:[VLine class]] && 3713 Diff([gg pointWithNum:0].y, [gg pointWithNum:1].y) <= TOLERANCE) 3714 w2Int = ( (w2-((int)w2)) < 0.2 ) ? (w2-1) : (w2); 3715 else 3716 w2Int = ( (w2-((int)w2)) > 0.5 ) ? (w2 + 1) : (w2); 3717 3718 if ( gFilled ) 3719 { 3720 [gg setWidth:0]; 3721 [(VPath*)gg setFillColor:( endW > 0 ) ? [NSColor grayColor] : nxWhite]; 3722 [(VPath*)gg drawWithPrincipal:nil]; 3723 drawed++; 3724 3725 if (w2Int) 3726 { 3727 [gg setColor:(endW > 0) ? nxWhite : nxBlack]; 3728 if ( [gg isKindOfClass:[VPath class]] ) 3729 [(VPath*)gg setFilled:NO optimize:NO]; 3730 else 3731 [gg setFilled:NO]; 3732 [gg setWidth:w2Int*2.0]; 3733 [gg drawWithPrincipal:nil]; 3734 } 3735 } 3736 else // stroked object 3737 { BOOL fillObj = ([gg respondsToSelector:@selector(setFillColor:)]) ? YES : NO; 3738 3739 if ( fillObj ) 3740 { [gg setWidth:0]; 3741 [(VPath*)gg setFillColor:( endW > 0 || endW < 0 ) ? nxBlack : nxWhite]; 3742 [(VPath*)gg drawWithPrincipal:nil]; 3743 drawed++; 3744 } 3745 if (w2Int) 3746 { [gg setColor:(endW > 0 || endW < 0) ? nxWhite : nxBlack]; 3747 if ( [gg isKindOfClass:[VPath class]] ) 3748 [(VPath*)gg setFilled:NO optimize:NO]; 3749 else 3750 [gg setFilled:NO]; 3751 [gg setWidth:w2Int*2.0]; 3752 [gg drawWithPrincipal:nil]; 3753 drawed++; 3754 } 3755 } 3756 /* set all values back to old */ 3757 [gg setWidth:oldGWidth]; 3758 [gg setColor:color]; 3759 if ( [gg respondsToSelector:@selector(setFillColor:)] ) 3760 { 3761 [(VPath*)gg setFillColor:fillColor]; 3762 if ( [gg isKindOfClass:[VPath class]] ) 3763 [(VPath*)gg setFilled:gFilled optimize:NO]; 3764 else 3765 [gg setFilled:gFilled]; 3766 } 3767 } 3768 } 3769 else 3770 { NSColor *fillColor = nil, *color = [[g color] retain]; 3771 3772 if ( [g respondsToSelector:@selector(setFillColor:)] ) 3773 fillColor = [[(VPath*)g fillColor] retain]; 3774 3775 /* need our half width/minWidth in pixel and scaled */ 3776 w2 = Abs(w+gWidth)*scale/2.0; 3777 if ([g isKindOfClass:[VLine class]] && 3778 Diff([g pointWithNum:0].y, [g pointWithNum:1].y) <= TOLERANCE) 3779 w2Int = ( (w2-((int)w2)) < 0.2 ) ? (w2-1) : (w2); 3780 else 3781 w2Int = ( (w2-((int)w2)) > 0.5 ) ? (w2 + 1) : (w2); 3782 3783 if ( gFilled ) 3784 { 3785 [g setWidth:0]; 3786 [(VPath*)g setFillColor:( endW > 0 ) ? [NSColor grayColor] : nxWhite]; 3787 [(VPath*)g drawWithPrincipal:nil]; 3788 drawed++; 3789 3790 if (w2Int) // w2Int 3791 { 3792 [g setColor:(endW > 0) ? nxWhite : nxBlack]; 3793 if ( [g isKindOfClass:[VPath class]] ) 3794 [(VPath*)g setFilled:NO optimize:NO]; 3795 else 3796 [g setFilled:NO]; 3797 [g setWidth:w2Int*2.0]; // w2Int*2.0 3798 [g drawWithPrincipal:nil]; 3799 } 3800 } 3801 else // stroked object 3802 { BOOL fillObj = ([g respondsToSelector:@selector(setFillColor:)]) ? YES : NO; 3803 3804 if ( fillObj ) 3805 { [g setWidth:0]; 3806 [(VPath*)g setFillColor:( endW > 0 || endW < 0 ) ? nxBlack : nxWhite]; 3807 [(VPath*)g drawWithPrincipal:nil]; 3808 drawed++; 3809 } 3810 if (w2Int) 3811 { [g setColor:(endW > 0 || endW < 0) ? nxWhite : nxBlack]; 3812 if ( [g isKindOfClass:[VPath class]] ) 3813 [(VPath*)g setFilled:NO optimize:NO]; 3814 else 3815 [g setFilled:NO]; 3816 [g setWidth:w2Int*2.0]; 3817 [g drawWithPrincipal:nil]; 3818 drawed++; 3819 } 3820 } 3821 /* set all values back to old */ 3822 [g setWidth:oldGWidth]; 3823 [g setColor:color]; 3824 if ( [g respondsToSelector:@selector(setFillColor:)] ) 3825 { 3826 [(VPath*)g setFillColor:fillColor]; 3827 if ( [g isKindOfClass:[VPath class]] ) 3828 [(VPath*)g setFilled:gFilled optimize:NO]; 3829 else 3830 [g setFilled:gFilled]; 3831 } 3832 } 3833 } 3834 if ( !drawed ) 3835 { [conView unlockFocus]; 3836 [win close]; 3837 return nil; 3838 } 3839 /* force 8 bit gray -> we must draw one thing gray */ 3840 { VRectangle *r=[VRectangle rectangle]; 3841 3842 [r setVertices:NSMakePoint(1.0,1.0) :NSMakePoint(1.0,1.0)]; 3843 [r setFillColor:[NSColor grayColor]]; 3844 [r setFilled:YES]; 3845 [r drawWithPrincipal:nil]; 3846 } 3847 3848 /* get pixel information into data (char string) */ 3849 rect.origin = NSZeroPoint; 3850 right = rect.size.width = (int)(conRect.size.width); /* our with scale and bounds calculated width */ 3851 height = rect.size.height = (int)(conRect.size.height); 3852 3853//[[NSColor redColor] set]; // test apple 3854//NSRectFill(NSMakeRect(1, 1, 1, 1)); 3855 3856 bitmapImage = [[NSBitmapImageRep allocWithZone:[self zone]] initWithFocusedViewRect:rect]; 3857 3858 // apple 3859 if ([bitmapImage bitsPerPixel] > 8 || ![bitmapImage isPlanar] || [bitmapImage samplesPerPixel] > 1) 3860 { NSBitmapImageRep *abitmap; 3861 3862 if ([bitmapImage bitsPerSample] == 8) // meshed 3863 { int ny, width; 3864 int bpr = [bitmapImage bytesPerRow], spp = 1, abpr; 3865 int bpp = [bitmapImage bytesPerPlane]; 3866 unsigned char *planes[5]; 3867 3868 abitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL 3869 pixelsWide:rect.size.width 3870 pixelsHigh:rect.size.height 3871 bitsPerSample:8 3872 samplesPerPixel:1 3873 hasAlpha:NO isPlanar:YES 3874 colorSpaceName:NSCalibratedWhiteColorSpace 3875 bytesPerRow:rect.size.width 3876 bitsPerPixel:8]; 3877 3878 data = [abitmap bitmapData]; 3879 abpr = [abitmap bytesPerRow]; 3880 [bitmapImage getBitmapDataPlanes:planes]; 3881 3882 if (![bitmapImage isPlanar]) 3883 spp = [bitmapImage bitsPerPixel]/8; 3884 width = bpr / spp; // bytesPerRow / samplesPerPixel 3885 for (y=0, ny=0; y<bpp; y+=bpr, ny+=abpr) 3886 { 3887 for (x=0; x<width; x++) 3888 { 3889 *((LONG*)(data+ny+x)) = *((LONG*)(planes[0]+y+x*spp)); 3890 } 3891 } 3892 } 3893 else 3894 { [conView unlockFocus]; 3895 [win close]; 3896 [bitmapImage release]; 3897 return nil; 3898 } 3899 [bitmapImage release]; 3900 bitmapImage = abitmap; 3901 } 3902 size = [bitmapImage bytesPerPlane]; 3903 data = [bitmapImage bitmapData]; 3904 bytesPerRow = [bitmapImage bytesPerRow]; 3905 bytesPerRowHalf = bytesPerRow/2.0; 3906 { int lineArray[bytesPerRowHalf], lineCnt = 0; 3907 NSPoint *pts; 3908 pts = malloc(right * sizeof(NSPoint)); 3909 3910 /* set loop parameters */ 3911 right -= (2*w2Int+1); 3912 height -= (2*w2Int+1); 3913 3914#if DEBUG_CONTUR 3915[nxGray set]; 3916#endif 3917 3918 /* vectorize contour */ 3919 start = 2*w2Int+1; 3920 for (y=start; y<height; y++) 3921 { int pCnt=0, byteY, byteX; 3922 3923 byteY = y * bytesPerRow; /* the height */ 3924 byteY = size - byteY - bytesPerRow; 3925 for (x=start; x<right && byteY+x+19 < size; x++) 3926 { 3927 byteX = byteY+x; 3928 if ( *((LONG*)(data+byteX)) == black ) 3929 { if ( *((LONG*)(data+byteX+4)) == black ) 3930 { if ( *((LONG*)(data+byteX+8)) == black ) 3931 { if ( *((LONG*)(data+byteX+12)) == black ) 3932 { if ( *((LONG*)(data+byteX+16)) == black ) 3933 { x += 16; continue; } 3934 else { x += 12; continue; } 3935 } 3936 else { x += 8; continue; } 3937 } 3938 else { x += 4; continue; } 3939 } 3940 else { continue; } 3941 } 3942 else if ( *((LONG*)(data+byteX-bytesPerRow-1)) == -1 && *((LONG*)(data+byteX-1)) == -1 && 3943 *((LONG*)(data+byteX+bytesPerRow-1)) == -1 ) 3944 { 3945 if ( *((LONG*)(data+byteX-bytesPerRow+3)) == -1 && *((LONG*)(data+byteX+3)) == -1 && 3946 *((LONG*)(data+byteX+bytesPerRow+3)) == -1 ) 3947 { 3948 if ( *((LONG*)(data+byteX-bytesPerRow+7)) == -1 && *((LONG*)(data+byteX+7)) == -1 && 3949 *((LONG*)(data+byteX+bytesPerRow+7)) == -1 ) 3950 { 3951 if ( *((LONG*)(data+byteX-bytesPerRow+11)) == -1 && *((LONG*)(data+byteX+11)) == -1 && 3952 *((LONG*)(data+byteX+bytesPerRow+11)) == -1 ) 3953 { 3954 if ( *((LONG*)(data+byteX-bytesPerRow+15)) == -1 && *((LONG*)(data+byteX+15)) == -1 && 3955 *((LONG*)(data+byteX+bytesPerRow+15)) == -1 ) 3956 { 3957 if ( *((LONG*)(data+byteX-bytesPerRow+19)) == -1 && *((LONG*)(data+byteX+19)) == -1 && 3958 *((LONG*)(data+byteX+bytesPerRow+19)) == -1 ) 3959 { x += 19; continue; } 3960 else { x += 15; continue; } 3961 } 3962 else { x += 11; continue; } 3963 } 3964 else { x += 7; continue; } 3965 } 3966 else { x += 3; continue; } 3967 } 3968 else { continue; } 3969 } 3970 if ( *(data+byteX) != white ) 3971 continue; 3972 /* l d r u is a black pixel -> one of our pixels */ 3973 if ( *(data+byteX-1) == black || *(data+byteX+bytesPerRow) == black || 3974 *(data+byteX+1) == black || *(data+byteX-bytesPerRow) == black ) 3975 { NSPoint nxp = {x, y}; 3976 pts[pCnt] = nxp; 3977 pCnt++; 3978#if DEBUG_CONTUR 3979//NSRectFill(NSMakeRect(x, y, 1, 1)); 3980#endif 3981 } 3982 } 3983 if ( pCnt ) 3984 [self buildPath:path :pts :pCnt :w :lineArray :&lineCnt]; 3985 } 3986 free(pts); 3987 } // lineArray, lineCnt 3988#if DEBUG_CONTUR 3989printf("%s Hour.Min.Sec vor Optimieren\n", [[[NSCalendarDate date] descriptionWithCalendarFormat:@"%H.%M.%S"] cString]); 3990#endif 3991 3992 /* correct path */ 3993 /*if ( [[path list] count] ) 3994 { for (x=(int)[[path list] count]-1; x>=0; x--) 3995 { VGraphic *lineG = [[path list] objectAtIndex:x]; // nach opt - nur singles ! 3996 NSPoint start, end; 3997 [(VLine*)lineG getVertices:&start :&end]; 3998 if ( //(![lineG isSelected] && Diff(start.x, end.x) <= 2 && Diff(start.y, end.y) <= 2) || 3999 (Diff(start.x, end.x) <= 1 && Diff(start.y, end.y) <= 1) ) 4000 [[path list] removeObjectAtIndex:x]; 4001 } 4002 }*/ 4003 [self optimizePath:path :w2Int]; 4004 4005 /* move and scale path AND oList to old great */ 4006 moveP.x = -moveP.x; moveP.y = -moveP.y; 4007 [path moveBy:moveP]; 4008 scale = 1/scale; 4009 [path scale:scale :scale withCenter:center]; 4010 4011 for (i=0; i < cnt; i++) 4012 [[oList objectAtIndex:i] moveBy:moveP]; 4013 for (i=0; i < cnt; i++) 4014 { VGraphic *g = [oList objectAtIndex:i]; 4015 4016 [g scale:scale :scale withCenter:center]; 4017 [g setDirty:NO]; 4018 } 4019 4020#if 0 4021{ int i; 4022 NSPoint s, e; 4023 4024 printf("VPath\n"); 4025 for (i=0; i<[[path list] count]; i++) 4026 { Line *l1=[[path list] objectAtIndex:i]; 4027 4028 [l1 getVertices:&s :&e]; 4029 printf("%.2f s.x\t %.2f s.y\t %.2f e.x\t %.2f e.y\n", s.x, s.y, e.x, e.y); 4030 } 4031 printf("\n3DLinePath\n"); 4032 for (i=0; i<[[linePath list] count]; i++) 4033 { VLine3D *l1=[[linePath list] objectAtIndex:i]; 4034 4035 [l1 getVertices:&s :&e]; 4036 printf("%.2f s.x\t %.2f s.y\t %.2f e.x\t %.2f e.y\n", s.x, s.y, e.x, e.y); 4037 } 4038} 4039#endif 4040 [conView unlockFocus]; 4041 [win close]; 4042 [bitmapImage release]; 4043#if DEBUG_CONTUR 4044printf("%s Hour.Min.Sec End\n\n", [[[NSCalendarDate date] descriptionWithCalendarFormat:@"%H.%M.%S"] cString]); 4045#endif 4046 return path; 4047} 4048 4049@end 4050