Hello again! I have a new problem today.
I have produced a contour plotter which uses values from measurement equipment to display enlarged deviations from nominal. This tool can scan through a file of multiple planes or parts of data to display any given contour. The trouble starts when the first contour plotted is fine, but the next and any subsequent contours are flipped on the 45 so Q4 becomes Q2. The tool allows to scan through contours and going back to contour 1, it is also flipped.
I can't seem to make it make sense and other JMP JSL savvy folks here have looked at the code and are also stumped. I'm attaching the script and a dummy file for processing. I have edited the data so a single coordinate is the same for all planes and demonstrates the "flipping" better.
/*
Contour/Distortion Plotter V0.1 (Development version)
Author: Wendy J Lawrence
Date: Feb 2019
Purpose: Plot contour for any given measurement equipment file regardless of source/origin
*/
Names default to here(0);
Clear globals();
Clear Symbols();
Clear log();
// Prompt user to direct to file and open
if(isempty(fpath),
dataloc = empty();
fpath = Pick File(
"Select *-plane.csv File to be processed:",
dataloc,
{"CSV Files|csv","Excel Files|csv;xls;xlsx", "All Files|*"},
1,
0,
"*plane*.csv"
);
);
print("File to be processed: " || fpath);
// Import CSV file
dt = Open(fpath,
Invisible(1),
Import Settings(
End Of Line( CRLF, CR, LF ),
End Of Field( Comma, CSV( 0 ) ),
Strip Quotes( 1 ),
Use Apostrophe as Quotation Mark( 0 ),
Scan Whole File( 1 ),
Treat empty columns as numeric( 0 ),
CompressNumericColumns( 0 ),
CompressCharacterColumns( 0 ),
CompressAllowListCheck( 0 ),
Labels( 1 ),
Column Names Start( 1 ),
Data Starts( 3 ),
Lines To Read( "All" ),
Year Rule( "20xx" )
)
);
//Conversion factor for source data units
if( Any( :units[1] == "English(in)", :units[1] == "Englisch(in)" ),
MeasConversion = 1,
MeasConversion = 25.4
);
Column_List = dt << Get Column Names( String );
GoodTitle = "Contour_Point";
PointList = {};
for( thisCol = 1, thisCol <= N Items( Column_List ), thisCol ++,
if( Starts With( Column_List[thisCol], GoodTitle ),
Insert Into( PointList, Column_List[thisCol] ),
)
);
//Convert the list of points into a matrix for plotting
MatTest = dt << Get As Matrix( PointList );
//Save the number of rows of planes for later use
RowsMatTest = N Rows( MatTest );
Radius = 2.9*25.4/2;
// ****Set variables and establish lists
//Reset the starting plane number with each new query
ThisPlane = 1;
ScaleFactor = 20; //( Distortion Factor to make differences visible )
LimitDiff = 5;
//Empty lists for the coordinates to plot the graph
lstLGX = {};
lstLGY = {};
lstXNom = {};
lstYNom = {};
for( Angle = 0, Angle <= 23, Angle++,
//formulas for Radians, dR Green, LG X, LG Y, x nom, y nom
Radians = Angle * 15 * pi() / 180;
if( MeasConversion == 1, dRGreenConv = 25.4, dRGreenConv = 1 );
dRGreen = MatTest[ ThisPlane, Angle + 1 ] * dRGreenConv; //convert Inches to mm, leave mm as is
ThisLGX = ( Radius + ScaleFactor*dRGreen ) * Cosine( Radians );
ThisLGY = ( Radius + ScaleFactor*dRGreen ) * Sine( Radians );
ThisXNom = ( Radius ) * Cosine( Radians );
ThisYNom = ( Radius ) * Sine( Radians );
Insert Into( lstLGX, ThisLGX );
Insert Into( lstLGY, ThisLGY );
Insert Into( lstXNom, ThisXNom );
Insert Into( lstYNom, ThisYNom );
);
//Insert the first radius into the last element of each list
lstLGX[25] = lstLGX[1];
lstLGY[25] = lstLGY[1];
lstXNom[25] = lstXNom[1];
lstYNom[25] = lstYNom[1];
//Matrix of each Radii
XCoord = Matrix( lstLGX );
YCoord = Matrix( lstLGY );
XNom = Matrix( lstXNom );
YNom = Matrix( lstYNom );
//Each plotted shape needs to have a Fit Circle for the Chart
obj = Fit Circle( XCoord, YCoord);
objNom = Fit Circle( XNom, YNom);
//===========================================================
//
// EXPRESSIONS/FUNCTIONS
//
//===========================================================
//Expression to establish plane, part and distortion factor on chart
UpdateCompVal = Expr(
tbPcNo << Set Text( dt:piece_number[ThisPlane] );
tbPlaneNo << Set Text( Char( dt:plane[ThisPlane] ) );
tbDataRow << Set Text( "Row in Data Table: " || Char( ThisPlane ) );
);
//Expression to reset the XY values for the contour display
UpdateXYCoord = Expr(
//reset the lists to properly update the contour plot
lstLGY = {};
lstLGX = {};
For( Angle = 0, Angle <= 23, Angle++,
//formulas for Radians, dR Green, LG X, LG Y, x nom, y nom
Radians = Angle * 15 * Pi() / 180;
If( MeasConversion == 1,
dRGreenConv = 25.4,
dRGreenConv = 1
);
dRGreen = MatTest[ThisPlane, Angle + 1] * dRGreenConv; //convert Inches to mm, leave mm as is
ThisLGY = (Radius + ScaleFactor * dRGreen) * Cosine( Radians );
ThisLGX = (Radius + ScaleFactor * dRGreen) * Sine( Radians );
Insert Into( lstLGX, ThisLGX, 1 );
Insert Into( lstLGY, ThisLGY, 1 );
);
//Insert the first radius into the last element of both lists
lstLGX[25] = lstLGX[1];
lstLGY[25] = lstLGY[1];
//Matrix of each Radii
XCoord = Matrix( lstLGX );
YCoord = Matrix( lstLGY );
//The plotted shape needs to have a Fit Circle for the Chart
obj = Fit Circle( XCoord, YCoord );
);
//for( i = 1, i <=24, i++, Print(Char( XCoord[i] ) || ", " || Char( YCoord[i]) ) )
//Exrpession to detail Custom Graph Display
RepaintGraph = Expr(
If( Round( Radius ) - Round( Radius, -1 ) >= 0,
AxisScale = Round( Radius, -1 ) + 10,
AxisScale = Round( Radius, -1 ) + 15
);
NegAxisScale = 0 - AxisScale;
gbContour = Graph Box(
X Scale( NegAxisScale, AxisScale ), //Get max and min from Diameter data from Product Master
Y Scale( NegAxisScale, AxisScale ),
X Axis( inc( 10 ) ),
Y Axis( inc( 10 ) ),
FrameSize( 500, 500 ),
X Name( "(mm)" ), // << Set Font Size( 15 ),
Y Name( "(mm)" ),
Marker( XCoord, YCoord ),
Line( XCoord, YCoord ),
Pen Color( "Green" );
Circle( {objNom[1], objNom[2]}, objNom[3] );
Pen Color( "Red" );
Line Style( "Dashed" );
Pen Color( "Black" );
Line Style( "Dotted" );
Line( [0, 0] , Matrix( {AxisScale, NegAxisScale} ) );
Line( Matrix( {NegAxisScale, AxisScale} ), [0, 0] );
);
);
//==============================================
//
// User Interface Window
//
//==============================================
//DO NOT MAKE MODAL!
ThisPlane = 1;
StopPlay = 0;
Contour_win = New Window( "Contour Plot",
//<< On Open( <<Move Window( 0, 0 ) ), //Doesn't do anything!
H Center Box(
H List Box(
V List Box(
tbDataRow = Text Box( "Row in Data Table: " || Char( ThisPlane ) )
),
H List Box(
Spacer Box( Size( 30, 10 ) ),
V List Box(
H Center Box(
H List Box(
bbPrev = Button Box( "Prev",
If( ThisPlane >= 2,
ThisPlane = ThisPlane - 1;
UpdateCompVal;
UpdateXYCoord;
)
),
bbNext = Button Box( "Next",
If( ThisPlane <= RowsMatTest - 1,
ThisPlane = ThisPlane + 1;
UpdateCompVal;
UpdateXYCoord;
)
)
)
),
Spacer Box( Size( 10, 15 ) ),
H Center Box(
V List Box(
H List Box(
bbAll = Button Box( "Play All",
bbNext << Enable( 0 );
bbPrev << Enable( 0 );
bbAll << Enable( 0 );
bbQuit << Enable( 0 );
ibStop << Set( 1 );
For( ThisPlane = 1, ThisPlane <= NRows( MatTest ), ThisPlane++,
Wait( 1 );
if( StopPlay == 0,
UpdateCompVal;
UpdateXYCoord;
,
bbNext << Enable( 1 );
bbPrev << Enable( 1 );
bbQuit << Enable( 1 );
bbAll << Enable( 1 );
ibStop << Set( 0 );
StopPlay = 0;
Stop();
)
);
bbNext << Enable( 1 );
bbPrev << Enable( 1 );
bbQuit << Enable( 1 );
bbAll << Enable( 1 );
ibStop << Set( 0 );
StopPlay = 0;
)
),
Spacer Box( Size( 10, 5 ) ),
tbTotalRows = Text Box( "Total Rows: " || Char( N Rows( MatTest ) ) ),
Spacer Box( Size( 10, 10 ) ),
V List Box( bbQuit = Button Box( "Quit",
Contour_win << Close Window;
Close( dt, No Save);
),
ibStop = If Box( 0, chkStop = Check Box( "Stop", chkStop << Set( 1, 0 ); StopPlay = 1 ) )
)
)
)
)
)
)
),
H Center Box(
V List Box(
Spacer Box( Size( 30, 10 ) ),
H Center Box(
H List Box(
tbPart = Text Box( "Part No: ", <<Set Font( "Arial Black", 13, "Bold" ) ),
tbPcNo = Text Box( dt:piece_number[ThisPlane], <<Set Font( "Arial Black", 13, "Bold" ) ),
Spacer Box( Size( 40, 10 ) ),
tbPlane = Text Box( "Plane Number: ", << Set Font( "Arial Black", 13, "Bold" ) ),
tbPlaneNo = Text Box( Char( dt:Plane[ThisPlane] ), << Set Font( "Arial Black", 13, "Bold" ) )
)
)
)
),
gb = RepaintGraph
);