This is ContourView.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "defs.h" #import "ContourView.h" #import <appkit/SavePanel.h> #import <appkit/color.h> #import <appkit/PrintPanel.h> #import <appkit/Button.h> #import <appkit/Pasteboard.h> extern int contour_(int *jdim, int *kdim, int *nj, int *nk, float *x, float *y, float *f, int *ncont, float *acont, float *ppxunit, float *ppyunit, int *colorMap); @implementation ContourView - (BOOL) acceptsFirstMouse { return YES;} /* grab that mouse down event! */ - clear:sender { NXEraseRect(&bounds); NXSetColor([contourParam provideBackGroundColor]); NXRectFill(&bounds); return self; } - setDrawColor:(float) color { PSsetgray(color); return self; } - drawSelf: (const NXRect *)rects :(int)rectCount{ BOOL functionDraw = [contourParam doDrawFunction]; BOOL gridDraw = [contourParam doDrawGrid]; BOOL clearPlot = [contourParam doClearPlot]; float xmin = [contourParam provideXmin]; float xmax = [contourParam provideXmax]; float ymin = [contourParam provideYmin]; float ymax = [contourParam provideYmax]; const char * maintitle = [contourParam provideMainTitle]; const char * functiontitle = [contourParam provideFunctionTitle]; const char * xtitle = "x"; const char * ytitle = "y"; char unitLabel[40]; id titleFont, labelFont; float xwid, yhgt=14.0; float xsave; float pattern0[] = {}; /* solid */ int viewChoice = [contourParam provideViewingChoice:self]; int viewPoint = [contourParam provideViewPoint:self]; float h,s,br; int inc_cont,icont,count_cont; int number_of_contours; /* the number of contour levels */ float *contour_levels; /* the contour level values */ NXColor color; int lineColor; lineColor = [contourParam provideContourLineColor]; if(clearPlot)[self clear:self]; NXSetColor([contourParam provideForeGroundColor]); if ([contourParam shouldChangeTitleFont]) { newTitleFont = [theFontManager convertFont:[theFontManager selFont]]; } if (newTitleFont) { titleFont = [Font newFont:[newTitleFont name] size:[newTitleFont pointSize] style:[newTitleFont style] matrix:NX_IDENTITYMATRIX]; yhgt = [newTitleFont pointSize]; } else { titleFont = [Font newFont:"Helvetica" size:14.0 style:0 matrix:NX_IDENTITYMATRIX]; yhgt = 14.0; } [titleFont set]; xwid = [titleFont getWidthOf:maintitle]; PSmoveto(XOFFSET/4.0 + (bounds.size.width - xwid)/2.0, bounds.size.height - 2.0 - yhgt); PSshow((char *)maintitle); if([contourParam shouldShowXYLabels]){ xwid = [titleFont getWidthOf:functiontitle]; PSmoveto(bounds.size.width-xwid-18., bounds.size.height-40.0); PSshow((char *)functiontitle); switch(viewChoice){ case 0: xtitle = "x"; ytitle = "y"; break; case 1: xtitle = "x"; ytitle = "z"; break; case 2: xtitle = "y"; ytitle = "z"; break; case 3: xtitle = "i"; ytitle = "j"; break; case 4: xtitle = "y"; ytitle = "x"; break; case 5: xtitle = "z"; ytitle = "x"; break; case 6: xtitle = "z"; ytitle = "y"; break; } xwid = [titleFont getWidthOf:xtitle]; PSmoveto(XOFFSET/4.0 + (bounds.size.width - xwid)/2.0, (bounds.origin.y + 10.0)); PSshow((char *)xtitle); xwid = [titleFont getWidthOf:ytitle]; yhgt = 10.0; PSmoveto((bounds.origin.x + 10.0 + yhgt), YOFFSET/4.0 + (bounds.size.height - xwid)/2.0); PSgsave(); PSrotate(90.0); PSshow((char *)ytitle); PSgrestore(); } PSgsave(); PStranslate(XOFFSET, YOFFSET); ppxunit = 0.88*(bounds.size.width-XOFFSET)/ABS(xmax-xmin); ppyunit = 0.88*(bounds.size.height-YOFFSET)/ABS(ymax-ymin); if([contourParam doSetAspectRatio]){ if(ABS(xmax-xmin) >= ABS(ymax-ymin)){ if(ABS(ymax-ymin)*ppxunit >= 0.88*(bounds.size.height-YOFFSET)) { ppxunit = ppyunit;} else {ppyunit = ppxunit; } } else{ if(ABS(xmax-xmin)*ppyunit >= 0.88*(bounds.size.width-XOFFSET)) { ppyunit = ppxunit;} else {ppxunit = ppyunit; } } } if(viewPoint == 1){ if(xmax > xmin){ xsave = xmax; xmax = xmin; xmin = xsave; [contourParam resetXmin:xmin]; [contourParam resetXmax:xmax]; } ppxunit = -ppxunit; } else{ if(xmax < xmin){ xsave = xmax; xmax = xmin; xmin = xsave; [contourParam resetXmin:xmin]; [contourParam resetXmax:xmax]; } } // try this // if(ppxunit >= ppyunit){ppyunit = ppxunit;} else { ppxunit = ppyunit;} xmin = xmin*ppxunit; /* drawing is all in pixel coordinates */ xmax = xmax*ppxunit; ymin = ymin*ppyunit; ymax = ymax*ppyunit; PStranslate(-xmin, -ymin); if(clearPlot){ PSsetlinewidth(0); NXSetColor([contourParam provideForeGroundColor]); PSnewpath(); /* draw bounding box */ PSmoveto(xmin, ymin); PSlineto(xmax, ymin); PSlineto(xmax, ymax); PSlineto(xmin, ymax); PSclosepath(); PSstroke(); /* finish bounding box */ if ([contourParam shouldChangeLabelFont]) { newLabelFont = [theFontManager convertFont:[theFontManager selFont]]; } if (newLabelFont) { labelFont = [Font newFont:[newLabelFont name] size:[newLabelFont pointSize] style:[newLabelFont style] matrix:NX_IDENTITYMATRIX]; yhgt = [newLabelFont pointSize]; } else { labelFont = [Font newFont:"Courier" size:12.0 style:0 matrix:NX_IDENTITYMATRIX]; yhgt = 12.0; } [labelFont set]; /* draw unit labels */ if([contourParam shouldShowUnitsLabel]){ PSmoveto(xmin, ymin - 4.0); /* xmin unit label */ PSsetdash(pattern0, 0, 0.0); PSrlineto(0.0, 4.0); PSstroke(); sprintf(unitLabel, "%10.4g", xmin/ppxunit); xwid = [labelFont getWidthOf:unitLabel]; PSmoveto(xmin - xwid/2.0, ymin - yhgt - 5.0); PSshow(unitLabel); PSmoveto(xmax, ymin - 4.0); /* xmax unit label */ PSsetdash(pattern0, 0, 0.0); PSrlineto(0.0, 4.0); PSstroke(); sprintf(unitLabel, "%10.4g", xmax/ppxunit); xwid = [labelFont getWidthOf:unitLabel]; PSmoveto(xmax - xwid/2.0, ymin - yhgt - 5.0); PSshow(unitLabel); PSmoveto(xmin - 4.0, ymin ); /* ymin unit label */ PSsetdash(pattern0, 0, 0.0); PSrlineto(4.0, 0.0); PSstroke(); sprintf(unitLabel, "%10.4g", ymin/ppyunit); xwid = [labelFont getWidthOf:unitLabel]; PSmoveto(xmin - xwid - 10.0, ymin + 2.0 - yhgt/2.0); PSshow(unitLabel); PSmoveto(xmin - 4.0, ymax ); /* ymax unit label */ PSsetdash(pattern0, 0, 0.0); PSrlineto(4.0, 0.0); PSstroke(); sprintf(unitLabel, "%10.4g", ymax/ppyunit); xwid = [labelFont getWidthOf:unitLabel]; PSmoveto(xmin - xwid - 10.0, ymax + 2.0 - yhgt/2.0); PSshow(unitLabel); } } /* MIN and MAX below in case xmin > xmax and/or ymin > ymax. */ PSrectclip(MIN(xmin,xmax), MIN(ymin,ymax), ABS(xmax-xmin), ABS(ymax-ymin)); if(gridDraw)[self gridAndDraw]; if(functionDraw)[self contourAndDraw]; PSgrestore(); if(clearPlot){ /* draw contour labels */ if([contourParam shouldShowContourValues]){ if ([contourParam shouldChangeLabelFont]) { newLabelFont = [theFontManager convertFont:[theFontManager selFont]]; } if (newLabelFont) { labelFont = [Font newFont:[newLabelFont name] size:[newLabelFont pointSize] style:[newLabelFont style] matrix:NX_IDENTITYMATRIX]; yhgt = [newLabelFont pointSize]; } else { labelFont = [Font newFont:"Courier" size:12.0 style:0 matrix:NX_IDENTITYMATRIX]; yhgt = 12.0; } [labelFont set]; number_of_contours = [contourParam provideContourNumber:self]; if(number_of_contours != 0){ contour_levels = [contourParam provideContourLevels:self]; sprintf(unitLabel, "%10.6g", contour_levels[0]); xwid = [labelFont getWidthOf:unitLabel]; inc_cont = 1; if(number_of_contours > 50)inc_cont =(int)(number_of_contours/20); count_cont = 0; for (icont=0; icont < number_of_contours; icont = icont + inc_cont) { count_cont = count_cont+1; switch(lineColor){ case 0: [self setDrawColor:NX_LTGRAY]; break; case 1: [self setDrawColor:NX_DKGRAY]; break; case 2: [self setDrawColor:NX_BLACK]; break; case 3: h = 0.6666*icont/(float)number_of_contours; s = 1.0; br = 1.0; color = NXConvertHSBToColor(h,s,br); NXSetColor(color); break; } sprintf(unitLabel, "%10.6g", contour_levels[icont]); PSmoveto(bounds.size.width-xwid-24., bounds.size.height-count_cont*(yhgt+3.0)-40.0); PSshow(unitLabel); } if(number_of_contours - count_cont*inc_cont != 0) { switch(lineColor){ case 0: [self setDrawColor:NX_LTGRAY]; break; case 1: [self setDrawColor:NX_DKGRAY]; break; case 2: [self setDrawColor:NX_BLACK]; break; case 3: h = 0.6666*1.0; s = 1.0; br = 0.6; color = NXConvertHSBToColor(h,s,br); NXSetColor(color); break; } sprintf(unitLabel, "%10.6g", contour_levels[number_of_contours]); PSmoveto(bounds.size.width-xwid-8., bounds.size.height-(count_cont+1)*(yhgt+3.0)-40.0); PSshow(unitLabel); } } } } return self; } - contourAndDraw { int colorMap; int lineColor = [contourParam provideContourLineColor]; function_part function; /* the struct of our function */ int number_of_contours; /* the number of contour levels */ float *contour_levels; /* the contour level values */ function = [contourParam provideFunction:self]; /* get function */ number_of_contours = [contourParam provideContourNumber:self]; contour_levels = [contourParam provideContourLevels:self]; if([contourParam doSolidLines])colorMap = 0; if(![contourParam doSolidLines])colorMap = 1; PSsetlinewidth([contourParam provideContourLineThickness]); switch(lineColor){ case 0: [self setDrawColor:NX_LTGRAY]; break; case 1: [self setDrawColor:NX_DKGRAY]; break; case 2: [self setDrawColor:NX_BLACK]; break; case 3: colorMap = 2; if(![contourParam doSolidLines])colorMap = 3; break; } contour_(&function.jmax, &function.kmax, &function.jmax, &function.kmax, function.x, function.y, function.f, &number_of_contours, contour_levels, &ppxunit, &ppyunit, &colorMap); return self; } - gridAndDraw { int i,j,k; grid_part grid; /* the struct of our function */ grid = [contourParam provideGrid:self]; /* get grid */ PSsetlinewidth([contourParam provideGridLineThickness]); NXSetColor([contourParam provideGridLineColor]); /* j family */ for (k=0; k < grid.kmax; k++){ i = k*grid.jmax; PSnewpath(); PSmoveto(grid.x[i]*ppxunit, grid.y[i]*ppyunit); for (j=1; j < grid.jmax; j++){ i = k*grid.jmax + j; PSlineto(grid.x[i]*ppxunit, grid.y[i]*ppyunit); } PSstroke(); } /* k family */ for (j=0; j < grid.jmax; j++){ PSnewpath(); PSmoveto(grid.x[j]*ppxunit, grid.y[j]*ppyunit); for (k=1; k < grid.kmax; k++){ i = k*grid.jmax + j; PSlineto(grid.x[i]*ppxunit, grid.y[i]*ppyunit); } PSstroke(); } return self; } - doPrinting:sender { /* to customize print panel */ id myPrintPanel = [PrintPanel new]; [ [NXApp printInfo] setMarginLeft:72.0 right:72.0 top:72.0 bottom:72.0 ]; if (bounds.size.height > bounds.size.width) { /* portrait mode */ if (bounds.size.height/bounds.size.width > 9.0/6.5) { [ [NXApp printInfo] setScalingFactor: 9.0*72.0/bounds.size.height]; } else { [ [NXApp printInfo] setScalingFactor: 6.5*72.0/bounds.size.width]; } [ [NXApp printInfo] setOrientation:NX_PORTRAIT andAdjust:YES ]; } else { /* landscape mode */ if (bounds.size.width/bounds.size.height > 9.0/6.5) { [ [NXApp printInfo] setScalingFactor: 9.0*72.0/bounds.size.width]; } else { [ [NXApp printInfo] setScalingFactor: 6.5*72.0/bounds.size.height]; } [ [NXApp printInfo] setOrientation:NX_LANDSCAPE andAdjust:YES ]; } [myPrintPanel setAccessoryView:printColorAccessory]; [self printPSCode:sender]; return self; } - mouseDown:(NXEvent *)e{ /* * This code taken from the Mandelbrot example in /NextDeveloper (and modified). * We implement the mouseDown method so the user can sweep out a section of * the view and select that as the current window in which to view the curve(s). */ int looping = YES; int oldMask; NXRect bbox; NXPoint startPoint, currPoint; float xmin, xmax, ymin, ymax; BOOL zooming = [contourParam doZoom]; if (zooming) { xmin = [contourParam provideXmin] * ppxunit; xmax = [contourParam provideXmax] * ppxunit; ymin = [contourParam provideYmin] * ppyunit; ymax = [contourParam provideYmax] * ppyunit; oldMask = [window addToEventMask:NX_MOUSEDRAGGEDMASK]; startPoint = e->location; [self convertPoint:&startPoint fromView:nil]; NXSetRect(&bbox,startPoint.x,startPoint.y,0.0,0.0); [self lockFocus]; while (looping) { e=[NXApp getNextEvent:NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK]; currPoint = e->location; [self convertPoint:&currPoint fromView:nil]; bbox.size.width = (currPoint.x - startPoint.x); bbox.size.height = (currPoint.y - startPoint.y); /* Normalize bbox to always have positive width and height */ if (bbox.size.width < 0) { bbox.size.width = -bbox.size.width; bbox.origin.x = startPoint.x - bbox.size.width; } if (bbox.size.height < 0) { bbox.size.height = -bbox.size.height; bbox.origin.y = startPoint.y - bbox.size.height; } /* * constrain the box to have the aspect ratio of the view. Choose * whichever dimension is closer to the desired result. */ PSnewinstance(); if (looping = (e->type == NX_MOUSEDRAGGED)) { PSsetinstance(YES); NXSetColor([contourParam provideForeGroundColor]); // PSsetgray(NX_BLACK); NXFrameRect(&bbox); PSsetinstance(NO); } } [self unlockFocus]; [window setEventMask:oldMask]; if ((bbox.size.width > 0) && (bbox.size.height > 0)) { /* At this point, bbox is in window coordinates. Convert to curve * coordinates based on this view's coordinates and the bounding box. */ xmin = xmin + (bbox.origin.x - XOFFSET); xmax = xmin + bbox.size.width; ymin = ymin + (bbox.origin.y - YOFFSET); ymax = ymin + bbox.size.height; /* save old min/max */ [contourParam stackOldMinMax:xmin/ppxunit :xmax/ppxunit :ymin/ppyunit :ymax/ppyunit]; [contourParam resetXmin:xmin/ppxunit]; [contourParam resetXmax:xmax/ppxunit]; [contourParam resetYmin:ymin/ppyunit]; [contourParam resetYmax:ymax/ppyunit]; /* Call [self display] to force current values of xmin/xmax/ymin/ymax * to take effect (otherwise xmin, etc., get incremented too many times). */ [contourParam drawPlotButton:1]; [self display]; [contourParam drawPlotButton:0]; } } return self; } - initFrame:(const NXRect *)frameRect { [super initFrame:frameRect]; /* a place to init stuff thp 6/12/91 */ return self; } - saveEPS:sender { id savePanel = [SavePanel new]; char *eps_fileName; // Name of the EPS file for output [savePanel setTitle:"SAVE EPS FILE"]; [savePanel setRequiredFileType:"eps"]; if ([savePanel runModal]) { eps_fileName = (char *)calloc(strlen([savePanel filename])+1, sizeof(char)); strcpy(eps_fileName, [savePanel filename]); [self savePSCode:eps_fileName]; } return self; } - savePSCode:(char *)aFile { NXStream *psStream; psStream = NXOpenMemory(NULL, 0, NX_WRITEONLY); if (!psStream) { return self; } [self getBounds:&bounds]; [self copyPSCodeInside:&bounds to:psStream]; NXFlush(psStream); NXSaveToFile(psStream, aFile); NXCloseMemory(psStream, NX_FREEBUFFER); return self; } /* * Following code taken from the Graph example in NextDeveloper/Examples. * * Copies the current view into the Pasteboard as PostScript. */ - copyPScode:sender { NXStream *psStream; id pb; char *data; int dataLen, maxDataLen; /* Open a stream on memory where we will collect the PostScript */ psStream = NXOpenMemory(NULL, 0, NX_WRITEONLY); if (!psStream) return self; /* Tell the Pasteboard we're going to copy PostScript */ pb = [Pasteboard new]; [pb declareTypes:&NXPostScriptPboardType num:1 owner:self]; /* writes the PostScript for the whole plot as EPS into the stream */ [self getBounds:&bounds]; [self copyPSCodeInside:&bounds to:psStream]; /* get the buffered up PostScript out of the stream */ NXGetMemoryBuffer(psStream, &data, &dataLen, &maxDataLen); /* put the buffer in the Pasteboard, free the stream (and the buffer) */ [pb writeType:NXPostScriptPboardType data:data length:dataLen]; NXCloseMemory(psStream, NX_FREEBUFFER); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.