This is CubeView.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "CubeView.h" #import "a3DViewerView.h" #import "dotAt.h" #import <stdlib.h> #import <strings.h> #import <stdio.h> #import <dpsclient/wraps.h> #import <dpsclient/dpsNeXT.h> #import <appkit/graphics.h> #import <appkit/Control.h> #import <appkit/Form.h> #import <appkit/OpenPanel.h> #import <appkit/Pasteboard.h> #import <appkit/Application.h> #import <appkit/Font.h> #import <appkit/Slider.h> #import <soundkit/Sound.h> #import <math.h> #define MAXLINE 1000 #define MAXNUM 10000 #define rad_to_deg (180./M_PI) @implementation CubeView + newFrame:(const NXRect *) frameRect { self = [super newFrame: frameRect]; [self initStatus]; return self; } + new; { self = [super new]; [self initStatus]; return self; } - (id)class { return [myController class]; } - (const char *)name { return [myController name]; } - (int)tag { return tag; } - (id)controllerObj { return myController; } - setController:(id)ctrlr { myController = ctrlr; [soundButton getFrame:&sndBtnRect]; [soundButton removeFromSuperview]; return self; } - setmachHeader:(struct mach_header *)mH { machHeader = mH; return self; } static char angle_buffer[20]; - (void)showError:(char *)errorMessage { NXRunAlertPanel("Error", errorMessage, "OK", NULL, NULL); } - (void)initStatus { toshow = (datapoints **) calloc(2000, sizeof(datapoints *)); max_path = 4000; path = (float *) calloc(2000, sizeof(float)); dot_offset[0] = 2.5 * 2 / bounds.size.width; dot_offset[1] = 2.5 * 2 / bounds.size.height; [self setDrawSize:(NXCoord) 2:(NXCoord) 2]; [self setDrawOrigin:(NXCoord) -1:(NXCoord) -1]; //showCube = YES; showCube = NO; showAxes = YES; //PSonly = NO; PSonly = YES; vm = [AzimuthMat new]; openReq = [OpenPanel new]; // establish the ops array and // bounding box for DPSDoUserPath() ops[0] = dps_moveto; ops[1] = 32 + 15; ops[2] = dps_lineto; boundingBox[0] = bounds.origin.x; boundingBox[1] = bounds.origin.y; boundingBox[2] = bounds.origin.x + bounds.size.width; boundingBox[3] = bounds.origin.y + bounds.size.height; // create the template plotting dot dot = [[NXImage alloc] initFromSection:"cubedot.tiff"]; // dot = [Bitmap newFromMachO:"cubedot.tiff"]; // dotgstate = [[dot window] gState]; // force a rescaling [self reScale:self]; tag = 63757374; // hex ascii for "cust" } - (void)printPSCode:sender { PSonly = YES; [self display]; [super printPSCode:self]; PSonly = NO; [self display]; } - copy:sender { id pb = [Pasteboard new]; NXStream *st; char *data; int length; int maxLength; PSonly = YES; [self display]; [pb declareTypes:&NXPostScriptPboardType num:1 owner:self]; st = NXOpenMemory( NULL, 0, NX_WRITEONLY ); [self copyPSCodeInside:NULL to:st]; NXGetMemoryBuffer( st, &data, &length, &maxLength ); [pb writeType:NXPostScriptPboardType data:data length:length]; NXCloseMemory( st, NX_FREEBUFFER ); PSonly = NO; [self display]; return self; } -(BOOL)acceptsFirstResponder { /* make this view accept first */ return YES; /* responder so it will understand copy */ } -resignFirstResponder { return self; } - setAngleDisplay:anObject { AngleDisplay = anObject; return self; } - setDistanceSlider:anObject { DistanceSlider = anObject; return self; } - setThetaSlider:anObject { ThetaSlider = anObject; return self; } - setPhiSlider:anObject { PhiSlider = anObject; return self; } - setSoundButton:anObject { soundButton = anObject; return self; } - Reset:sender { [vm setTheta:0.]; [ThetaSlider setFloatValue:0.]; [vm setPhi:0.]; [PhiSlider setFloatValue:0.]; [vm setdist:2.0]; [DistanceSlider setFloatValue:-1/2.]; [self ShowAngles:sender]; [self display]; return self; } - (void)ShowAngles:sender { sprintf(angle_buffer, "%6.2f", rad_to_deg*[vm getTheta:self]); [AngleDisplay setStringValue:angle_buffer at:0]; sprintf(angle_buffer, "%6.2f", -rad_to_deg*[vm getPhi:self]); [AngleDisplay setStringValue:angle_buffer at:1]; sprintf(angle_buffer, "%6.2f", [vm getdist:self]); [AngleDisplay setStringValue:angle_buffer at:2]; } - (float)readPhi { return -rad_to_deg*[vm getPhi:self]; } - (float)readTheta { return rad_to_deg*[vm getTheta:self]; } - (float)readInvdist { return [vm getdist:self]; } - (BOOL)writePhi:(float)phi { float angle; double min,max; BOOL correct=NO; angle = phi/rad_to_deg; if( angle > (max = [PhiSlider maxValue]) ) {angle = max;correct=YES;} if( angle < (min = [PhiSlider minValue]) ) {angle = min;correct=YES;} [vm setPhi:-angle]; [PhiSlider setFloatValue:angle]; [self display]; return correct; } - (BOOL)writeTheta:(float)tht { float angle; double min,max; BOOL correct=NO; angle = tht/rad_to_deg; if( angle > (max = [ThetaSlider maxValue]) ) {angle = max;correct=YES;} if( angle < (min = [ThetaSlider minValue]) ) {angle = min;correct=YES;} [vm setTheta:angle]; [ThetaSlider setFloatValue:angle]; [self display]; return correct; } - (BOOL)writeInvdist:(float)invd { float id; double min,max; BOOL correct=NO; id = -1./invd; if( id > (max = [DistanceSlider maxValue]) ) {id = max;correct=YES;} if( id < (min = [DistanceSlider minValue]) ) {id = min;correct=YES;} id = -1./id; [vm setdist:id]; [DistanceSlider setFloatValue:-1./id]; [self display]; return correct; } - (void)setViewParameters { [self writePhi:currentPhi]; [self writeTheta:currentTheta]; [self writeInvdist:currentDist]; } - setTheta:sender { [vm setTheta:[sender floatValue]]; [self display]; [myController perform:@selector(resetFirstResponder:) with:self afterDelay:1 cancelPrevious:YES]; return self; } - setPhi:sender { [vm setPhi:-[sender floatValue]]; [self display]; [myController perform:@selector(resetFirstResponder:) with:self afterDelay:1 cancelPrevious:YES]; return self; } - setdist:sender { float dist; dist = [sender floatValue]; if (dist < 1.8) { [self showError: "Distance must be greater than 1.8"]; return self; } [vm setdist:dist]; [DistanceSlider setFloatValue:-1./dist]; [self display]; return self; } - setinvdist:sender { [vm setinvdist:-[sender floatValue]]; [self display]; [myController perform:@selector(resetFirstResponder:) with:self afterDelay:1 cancelPrevious:YES]; return self; } - setTheta_degrees:sender { float angle = [sender floatValue]/rad_to_deg; [vm setTheta:angle]; [ThetaSlider setFloatValue:angle]; [self display]; return self; } - setPhi_degrees:sender { float angle = [sender floatValue]/rad_to_deg; [vm setPhi:-angle]; [PhiSlider setFloatValue:angle]; [self display]; return self; } - toggleCube:sender { showCube = showCube ? NO : YES; [self display]; [myController perform:@selector(resetFirstResponder:) with:self afterDelay:1 cancelPrevious:YES]; return self; } - toggleAxes:sender { showAxes = showAxes ? NO : YES; [self display]; [myController perform:@selector(resetFirstResponder:) with:self afterDelay:1 cancelPrevious:YES]; return self; } - reScale:sender { float maxval[3], minval[3], limits[6], *fpt; datapoints **all_lines = toshow, *thisline; short int i, count; if (*all_lines == (datapoints *) NULL) { /* no data - set to defaults */ limits[0] = limits[1] = limits[2] = 0.; limits[3] = limits[4] = limits[5] = 1.; [self setlimits:limits]; return self; } for(i = 0; i < 3; i++) minval[i] = maxval[i] = *((*all_lines)->displayed[i]); while (thisline = *all_lines++) { for(i = 0; i < 3; i++) { count = thisline->npts; fpt = thisline->displayed[i]; while (count--) { if (*fpt < minval[i]) minval[i] = *fpt; if (*fpt > maxval[i]) maxval[i] = *fpt; fpt++; } } } for(i = 0; i < 3; i++) { if (minval[i] >= maxval[i]) minval[i] = maxval[i] - 1; limits[i] = minval[i] - 0.035*(maxval[i] - minval[i]); limits[i + 3] = maxval[i] + 0.035*(maxval[i] - minval[i]); } [self setlimits:limits]; return self; } - (void)setViewSound:(id)sndObj { if( !viewSound ) viewSound = [Sound new]; [viewSound copySound:sndObj]; [self showSoundButton]; [myController perform:@selector(resetFirstResponder:) with:self afterDelay:1 cancelPrevious:YES]; } - (void)deleteViewSound { if( viewSound ) { [viewSound free]; viewSound = 0x0; [[self window] disableFlushWindow]; [soundButton removeFromSuperview]; [[self window] display]; [[self window] reenableFlushWindow]; [[self window] flushWindow]; [myController perform:@selector(resetFirstResponder:) with:self afterDelay:1 cancelPrevious:YES]; } } - (void)showSoundButton { [[self window] disableFlushWindow]; [[self superview] addSubview:soundButton]; [soundButton moveTo:sndBtnRect.origin.x :sndBtnRect.origin.y]; [[self window] display]; [[self window] reenableFlushWindow]; [[self window] flushWindow]; } - playSound:sender { [viewSound play]; return self; } - (char *)currentDataFile { return dataFileName; } - openData:sender { const char *fileName; const char *const ext[2] = {"3d", NULL}; if([openReq runModalForTypes:ext] && (fileName = [openReq filename])) { [self readData:fileName]; if( dataFileName ) free(dataFileName); dataFileName = malloc(BUFSIZ); strcpy(dataFileName,fileName); } else [self showError:"No file chosen or could not open file"]; return self; } static void float_copy (register int n, register float * to, register int to_inc, register float * from, register int from_inc) { if (n > 0) while (n--) { *to = *from; to += to_inc; from += from_inc; } } - (BOOL) readData:(const char *)filename { FILE *input; float *scratch, *fpt; char thisline[MAXLINE], *cpt, c; long int count, ncols, nchars, nlines, expected_cols; datapoints **all_data = toshow, *thesedata; scratch = (float *) calloc(MAXNUM, sizeof(float)); if((input = fopen(filename, "r")) == NULL) { sprintf(thisline, "Unable to open file %s", filename); [self showError:thisline]; return NO; } /* release existing data */ while ((thesedata = *all_data) != (datapoints *) NULL) { free(thesedata->displayed); count = 0; while(thesedata->all[count] != (float *) NULL) { free(thesedata->all[count]); count++; } free(thesedata->all); free(thesedata); *all_data++ = (datapoints *) NULL; } all_data = toshow; /* read new data */ fgets(thisline, MAXLINE, input); while (!feof(input)) { if(!sscanf(thisline, " %1s ", &c)) { sprintf(thisline, "Unable to read a specification from %s", filename); [self showError:thisline]; return NO; } switch(c) { case 'N': case 'n': case 'L': case 'l': case 'P': case 'p': case 'B': case 'b': fgets(thisline, MAXLINE, input); /* load a new line */ break; case 'C': case 'c': /* next line contains an RGB color */ fgets(thisline, MAXLINE, input); break; default: sprintf(thisline, "the beginning of %s doesn't look like a specification", filename); [self showError:thisline]; return NO; } cpt = thisline; fpt = scratch; ncols = 0; while(sscanf(cpt, "%f%n", fpt, &nchars) == 1) { /* removed space bewteen %f %n */ cpt += nchars; ncols++; fpt++; } if (ncols == 0) { sprintf(thisline, "First line of %s does not contain numeric data", filename); [self showError:thisline]; return NO; } /* digest the rest of the lines */ expected_cols = ncols; nlines = 1; while(fgets(thisline, MAXLINE, input) != NULL) { cpt = thisline; ncols = 0; while(sscanf(cpt, "%f%n", fpt, &nchars) == 1) { /* removed space bewteen %f %n */ cpt += nchars; ncols++; fpt++; } if (!ncols) break; nlines++; if (ncols != expected_cols) { sprintf(thisline, "Expected %d values but got %d values at line %d\n", expected_cols, ncols, nlines); [self showError:thisline]; return NO; } } /* create the datapoints structure and */ /* store the values */ thesedata = *all_data++ = (datapoints *) malloc(sizeof(datapoints)); switch(c) { case 'N': case 'n': thesedata->type = NEITHER; break; case 'L': case 'l': thesedata->type = LINES; break; case 'P': case 'p': thesedata->type = POINTS; break; case 'B': case 'b': thesedata->type = BOTH; break; case 'C': case 'c': thesedata->type = COLOR; break; } thesedata->all = (float **)calloc((size_t) expected_cols + 1, (size_t) sizeof(float *)); for(ncols = 0; ncols < expected_cols; ncols++) { thesedata->all[ncols] = (float *)calloc((size_t) nlines, sizeof(float)); float_copy(nlines, thesedata->all[ncols], 1, scratch + ncols, expected_cols); } thesedata->all[expected_cols] = (float *)NULL; /* make sure path is large enough */ if (2*nlines > max_path) realloc(path, (2*nlines)*sizeof(float)); thesedata->npts = nlines; memmove(thesedata->displayed = (float **) calloc(3, sizeof(float *)), thesedata->all, 3 * sizeof(float *)); } [self reScale:self]; free(scratch); fclose(input); [self display]; return YES; } static int x_seq[] = {0,3,3,0,0,0,3,3,0,0,3,3,3,3,0,0}; static int y_seq[] = {1,1,4,4,1,1,1,4,4,1,1,1,4,4,4,4}; static int z_seq[] = {2,2,2,2,2,5,5,5,5,5,5,2,2,5,5,2}; -setlimits:(float *)newlimits { int i, n, tickdir; float tick, width; for (n = 0; n < 16; n++) { /* create cube */ cube[0][n] = newlimits[x_seq[n]]; cube[1][n] = newlimits[y_seq[n]]; cube[2][n] = newlimits[z_seq[n]]; } for (n = 0; n < 54; n++) { /* create axes */ axes[0][n] = newlimits[0]; axes[1][n] = newlimits[1]; axes[2][n] = newlimits[2]; } for (i = 0; i < 3; i++) { tickdir = (i == 0) ? 1 : 0; tick = 0.03 * (newlimits[tickdir + 3] - newlimits[tickdir]); width = newlimits[i + 3] - newlimits[i]; n = 18 * i; axes[i][n+1] = axes[i][n+2] = axes[i][n+3] = axes[i][n+4] = newlimits[i] + 0.25 * width; axes[i][n+5] = axes[i][n+6] = axes[i][n+7] = axes[i][n+8] = newlimits[i] + 0.5 * width; axes[i][n+9] = axes[i][n+10] = axes[i][n+11] = axes[i][n+12] = newlimits[i] + 0.75 * width; axes[i][n+13] = axes[i][n+17] = newlimits[i] + 0.87 * width; axes[i][n+14] = axes[i][n+16] = newlimits[i] + 0.84 * width; axes[i][n+15] = newlimits[i] + width; axes[tickdir][n+2] = axes[tickdir][n+6] = axes[tickdir][n+10] = axes[tickdir][n+14] = newlimits[tickdir] + tick; axes[tickdir][n+3] = axes[tickdir][n+7] = axes[tickdir][n+11] = axes[tickdir][n+16] = newlimits[tickdir] - tick; } [vm setlimits:newlimits]; [self Reset:self]; return self; } - drawSelf:(NXRect*)r :(int)c { NXColor lineColor; datapoints **all_lines = toshow, *thisline; NXEraseRect(&bounds); PSsetgray(NX_BLACK); PSsetlinewidth(0.0); if (showCube) { ops[1] = 32 + 16 - 1; DPSDoUserPath ([vm as_DPSpath :16 :cube[0] :cube[1] :cube[2] :path], 32, dps_float, ops, 3, boundingBox, dps_ustroke); } if (showAxes) { ops[1] = 32 + 54 - 1; DPSDoUserPath ([vm as_DPSpath :54 :axes[0] :axes[1] :axes[2] :path], 108, dps_float, ops, 3, boundingBox, dps_ustroke); } while((thisline = *all_lines++) != (datapoints *) NULL) { if (thisline->type & 0x4) { /* set the RGB color */ lineColor = NXConvertRGBToColor(*(thisline->displayed)[0], *(thisline->displayed)[1], *(thisline->displayed)[2]); NXSetColor(lineColor); continue; } if( thisline->type & 0x1 && thisline->npts > 1 ) { /* draw the line */ ops[1] = thisline->npts + 32 - 1; DPSDoUserPath([vm as_DPSpath :thisline->npts :(thisline->displayed)[0] :(thisline->displayed)[1] :(thisline->displayed)[2] :path], 2*(thisline->npts), dps_float, ops, 3, boundingBox, dps_ustroke); } if (thisline->type & 0x2) { /* draw points */ if (PSonly) dotAtPSonly([vm as_DPSpath :thisline->npts :(thisline->displayed)[0] :(thisline->displayed)[1] :(thisline->displayed)[2] :path], 2 *(thisline->npts), *dot_offset); else dotAt([vm as_DPSpath :thisline->npts :(thisline->displayed)[0] :(thisline->displayed)[1] :(thisline->displayed)[2] :path offset:dot_offset], 2 * (thisline->npts), dotgstate); } } return self; } - (BOOL)acceptsFirstMouse { return YES; } - mouseDown:(NXEvent *)e { if( e->data.mouse.click == 2 ) { [myController inspectCustomComponent]; return self; } if( e->flags & NX_COMMANDMASK ) { [self toggleCube:self]; } else if (e->flags & NX_ALTERNATEMASK ) { [self toggleAxes:self]; } else { [myController refreshInspectorPanel]; } return [super mouseDown:e]; } - free { int count; datapoints **all_data = toshow, *thesedata; while ((thesedata = *all_data) != (datapoints *) NULL) { free(thesedata->displayed); count = 0; while(thesedata->all[count] != (float *) NULL) { free(thesedata->all[count]); count++; } free(thesedata->all); free(thesedata); *all_data++ = (datapoints *) NULL; } free(toshow); if( viewSound ) [viewSound free]; if( dataFileName ) free(dataFileName); return [super free]; } - write:(NXTypedStream *)stream { int cols, nstruct, ns; datapoints **all_data = toshow, *thesedata; [super write:stream]; NXWriteType(stream, "i", &max_path); nstruct = 0; while((thesedata = *all_data++) != (datapoints *) NULL) nstruct++; NXWriteType(stream, "i", &nstruct); all_data = toshow; for( ns=0; ns<nstruct; ns++) { thesedata = *all_data++; NXWriteTypes(stream, "ii", &thesedata->npts, &thesedata->type); cols = 0; while( thesedata->all[cols] != (float *) NULL) { NXWriteArray(stream, "f", thesedata->npts, *(&thesedata->all[cols])); cols++; } } NXWriteObject(stream, AngleDisplay); NXWriteObject(stream, PhiSlider); currentPhi = -rad_to_deg * [vm getPhi:self]; NXWriteObject(stream, ThetaSlider); currentTheta = rad_to_deg * [vm getTheta:self]; NXWriteObject(stream, DistanceSlider); currentDist = [vm getdist:self]; NXWriteTypes(stream, "fff", ¤tPhi, ¤tTheta, ¤tDist); NXWriteObject(stream, soundButton); NXWriteRect(stream, &sndBtnRect); NXWriteObject(stream, viewSound); NXWriteTypes(stream, "ccc", &showCube, &showAxes, &PSonly); NXWriteType(stream, "*", &dataFileName); NXWriteObject(stream, myController); return self; } - read:(NXTypedStream *)stream { int cols, nstruct, ns; datapoints **all_data, *thesedata; int ncols = 3; [super read:stream]; NXReadType(stream, "i", &max_path); NXReadType(stream, "i", &nstruct); toshow = (datapoints **) calloc(1000, sizeof(datapoints *)); all_data = toshow; for( ns=0; ns<nstruct; ns++) { thesedata = *all_data++ = (datapoints *) malloc(sizeof(datapoints)); NXReadTypes(stream, "ii", &thesedata->npts, &thesedata->type); thesedata->all = (float **)calloc((size_t) ncols+1, (size_t) sizeof(float *)); for( cols=0; cols<ncols; cols++ ) { thesedata->all[cols] = (float *)calloc((size_t) thesedata->npts, sizeof(float)); NXReadArray(stream, "f", thesedata->npts, *(&thesedata->all[cols])); } thesedata->all[ncols] = (float *)NULL; memmove(thesedata->displayed = (float **) calloc(3, sizeof(float *)), thesedata->all, 3 * sizeof(float *)); } AngleDisplay = NXReadObject(stream); PhiSlider = NXReadObject(stream); ThetaSlider = NXReadObject(stream); DistanceSlider = NXReadObject(stream); NXReadTypes(stream, "fff", ¤tPhi, ¤tTheta, ¤tDist); soundButton = NXReadObject(stream); NXReadRect(stream, &sndBtnRect); viewSound = NXReadObject(stream); NXReadTypes(stream, "ccc", &showCube, &showAxes, &PSonly); NXReadType(stream, "*", &dataFileName); myController = NXReadObject(stream); return self; } - awake { [super awake]; [myController setViews:self]; path = (float *) calloc(2000, sizeof(float)); dot_offset[0] = 2.5 * 2 / bounds.size.width; dot_offset[1] = 2.5 * 2 / bounds.size.height; [self setDrawSize:(NXCoord) 2:(NXCoord) 2]; [self setDrawOrigin:(NXCoord) -1:(NXCoord) -1]; showCube = NO; showAxes = YES; PSonly = YES; ops[0] = dps_moveto; ops[1] = 32 + 15; ops[2] = dps_lineto; boundingBox[0] = bounds.origin.x; boundingBox[1] = bounds.origin.y; boundingBox[2] = bounds.origin.x + bounds.size.width; boundingBox[3] = bounds.origin.y + bounds.size.height; vm = [AzimuthMat new]; openReq = [OpenPanel new]; [self reScale:self]; tag = 63757374; // hex ascii for "cust" [self setViewParameters]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.