This is ParameterController.m in view mode; [Download] [Up]
// ParameterController.m // By Charles G. Fleming, Halchin and Fleming. // You may freely copy, distribute and reuse this code. // Halchin and Fleming, and the author disclaim any warranty of any kind, // expressed or implied, as to its fitness for any particular use. #import "ParameterController.h" #import <stdlib.h> #import <strings.h> #import "MathTool.h" #import "MathGraph.h" #import <appkit/TextField.h> #import <appkit/ScrollView.h> #import <appkit/Text.h> #import <appkit/Font.h> #import "DomainAndRange.h" #import <appkit/Button.h> #import <appkit/Window.h> #import <appkit/Button.h> #import <appkit/defaults.h> // for NXArgv #import <sys/param.h> // for MAXPATHLEN #import <libc.h> // for chdir, getwd @implementation ParameterController // Start Mathematica and load the package "Laplace". Modify the scroll view // that will display the nongraphical results. Bring the windows on // screen in the order desired. - appDidInit:sender { char *commandString; char packagePath[MAXPATHLEN], fullPath[MAXPATHLEN], *suffix; // This will set up and start Mathematica. [mathTool initMath:self]; // Clear the variable t in Mathematica. Send 1 to be evaluated so that Mathematica doesn't // say that NULL was returned. [mathTool executeCommand:"Clear[t]; 1" resultType:INPUT]; // Set up the path to the Mathematica package Laplace.m. strcpy(packagePath, NXArgv[0]); if (suffix = rindex(packagePath, '/')) *suffix = '\0'; if(packagePath) // appPath is the pathname of a directory. chdir causes the chdir(packagePath); // directory to become the current working directory. getwd(packagePath); // This copies the absolute pathname of the current working // directory into appPath. sprintf(fullPath, "%s/Laplace.m",packagePath); // Construct the string that will be used to load the Laplace Transform // package. commandString = malloc(MAXPATHLEN); sprintf(commandString, "<<%s", fullPath); // Send the command to the MathTool. Get the result from the MathTool, // (it will be null) but do not display it. [mathTool executeCommand:commandString resultType:NONE]; free(commandString); // Set up the scroll view so that it can handle Mathematica's output. [[resultScrollView docView] setFont:[Font newFont:"Courier" size:12]]; // Widen the margins in the scroll view to make Mathematica's output // about 1/8 inch from the margins. [[resultScrollView docView] setMarginLeft:5 right:5 top:5 bottom:5]; // Bring the windows on screen. [[mathGraph window] orderFront:sender]; [[resultScrollView window] orderFront:sender]; [self makeKeyAndOrderFront:sender]; // This flag is used to detect whether or not the result view and graph // view may need to be cleared. notCleared = NO; return self; } // Solve the differential equation using a the function "Laplace". - compute:sender { char *commandString, *resultString; float mass, friction, springConstant, forcingFrequency; float forcingMagnitude, initialPosition, initialVelocity; // Get the current values from all of the fields. mass = [massField floatValue]; friction = [frictionField floatValue]; springConstant = [springConstantField floatValue]; forcingFrequency = [forcingFrequencyField floatValue]; forcingMagnitude = [forcingMagnitudeField floatValue]; initialPosition = [initialPositionField floatValue]; initialVelocity = [initialVelocityField floatValue]; // Construct the string that will be used to execute the "Laplace" // command to solve the differential equation. commandString = malloc(500); sprintf(commandString, "Laplace[%f,%f,%f,%f,%f,%f,%f]", mass, friction, springConstant, forcingMagnitude, forcingFrequency, initialPosition, initialVelocity); // Send the command to the MathTool and get the result in a form // suitable for displaying. [mathTool executeCommand:commandString resultType:OUTPUT]; resultString = [mathTool outputTextString]; // Display the result in the scroll view. [[resultScrollView window] orderFront:self]; [[resultScrollView docView] setText:resultString]; // Also get the result from Mathematica in a form that can be used // for generating graphics. [mathTool executeCommand:commandString resultType:INPUT]; solution = [mathTool inputTextString]; // Enable the graphics buttons so that the solution can be plotted. [plotButton setEnabled:YES]; [graphSettingsButton setEnabled:YES]; // This is used to detect whether or not the result view and graph // view may need to be cleared. notCleared = YES; free(commandString); return self; } // Display the solution obtained using "Laplace". - plotSolution:sender { char *commandString, *graphicsString; double domainLowerBound, domainUpperBound, rangeLowerBound; double rangeUpperBound, aspectRatio; // Build the command to generate the graphics and get the graphics // string from Mathematica. // First get the domain and range from the domainAndRange window. if([[domainAndRange defaultButton:self] state]) { domainLowerBound = [domainAndRange domainLower]; domainUpperBound = [domainAndRange domainUpper]; commandString = malloc(50 + strlen(solution)); sprintf(commandString, "Plot[%s, {t, %f, %f}]", solution, domainLowerBound, domainUpperBound); } else { domainLowerBound = [domainAndRange domainLower]; domainUpperBound = [domainAndRange domainUpper]; rangeLowerBound = [domainAndRange rangeLower]; rangeUpperBound = [domainAndRange rangeUpper]; aspectRatio = (rangeUpperBound - rangeLowerBound)/ (domainUpperBound - domainLowerBound); commandString = malloc(160 + strlen(solution)); sprintf(commandString, "Plot[%s, {t, %f, %f}, PlotRange->{%f, %f}, AspectRatio->%f]", solution, domainLowerBound, domainUpperBound, rangeLowerBound, rangeUpperBound, aspectRatio); } // Send the Plot command to Mathematica. [mathTool executeCommand:commandString resultType:GRAPHICS]; graphicsString = [mathTool graphicsString]; // Graph the result. [[mathGraph window] orderFront:self]; [mathGraph display:graphicsString]; free(commandString); return self; } // Whenever a slider moves, place its value into the corresponding field. - setValues:sender { int tag; // Find which slider moved. tag = [sender tag]; // Put the slider's value in the field. switch (tag) { case 0: [massField setFloatValue:[sender floatValue]]; break; case 1: [frictionField setFloatValue:[sender floatValue]]; break; case 2: [springConstantField setFloatValue:[sender floatValue]]; break; case 3: [forcingMagnitudeField setFloatValue:[sender floatValue]]; break; case 4: [forcingFrequencyField setFloatValue:[sender floatValue]]; break; case 5: [initialPositionField setFloatValue:[sender floatValue]]; break; case 6: [initialVelocityField setFloatValue:[sender floatValue]]; break; } // Clear only when necessary. if (notCleared) { // Disable the graphics buttons until the solve button has // been pushed again. Clear the displays. [plotButton setEnabled:NO]; [graphSettingsButton setEnabled:NO]; [mathGraph clearMathGraph]; [[resultScrollView docView] setText:""]; notCleared = NO; } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.