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.