cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
  • Register to attend Discovery Summit 2025 Online: Early Users Edition, Sept. 24-25.
  • New JMP features coming to desktops everywhere this September. Sign up to learn more at jmp.com/launch.
Choose Language Hide Translation Bar
PhamBao
Level III

How to make closewise continuous polygon with matrix

Hi all,
x_matrix = [59, 60, 62, 64, 68, 70, 80, 118, 130, 182, 461, 678, 696, 700, 701, 701, 701];
y_matrix = [44.07, -44.31, 105.11, -66.88, 132.65, -88.02, -91.87, -104.49, 116.54, -106.6, -108.17, -55.48, -95.9, -93, -87.98, -87.47, -69.45];

I have matrix above. Is there any way to convert or sort them into continuous closewise polygon

If my matrix x and y are not from convex polygon, is there any way to do so

Thanks

2 ACCEPTED SOLUTIONS

Accepted Solutions
Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

this is close:

x_matrix = [59, 60, 62, 64, 68, 70, 80, 118, 130, 182, 461, 678, 696, 700, 701, 701, 701];
y_matrix = [44.07, -44.31, 105.11, -66.88, 132.65, -88.02, -91.87, -104.49, 116.54, -106.6, -108.17, -55.48, -95.9, -93, -87.98, -87.47, -69.45];
t = Triangulation( x( x_matrix, y_matrix ) );
order = t << gethullpoints;
xs = x_matrix[order];
ys = y_matrix[order];
dt = As Table( xs || ys );
Graph Builder(
	Size( 669, 491 ),
	Show Control Panel( 0 ),
	Variables( X( :Col1 ), Y( :Col2 ) ),
	Elements( Line( X, Y, Legend( 7 ), Ordering( "Row Order" ) ), Points( X, Y, Legend( 8 ) ) )
);

Craige_Hales_0-1752695494108.png

Search the scripting index for "hull" and you'll find the alpha shape function as well. the Triangulation function can also tell you about points inside the hull and how they form a Delaunay triangulation. If you care about clockwise vs counter clockwise, https://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-cloc...

 

I'm at the limit of my understanding, but I'd be fascinated to learn more about what you are doing.

@danschikore 

 

Craige

View solution in original post

Re: How to make closewise continuous polygon with matrix

Thanks for the example @Craige_Hales - alpha shapes are definitely interesting for cases like this, since @PhamBao mentioned non-convex solutions.  When the input is a polygon, the results might not be quite what you expect.  The example below demonstrates the use of alpha shapes on a set of points.  The alpha shape is a subset of the Delaunay triangulation, which could include points, edges, and triangles.  In JMP, the alpha shape is showing you the only the triangles.  For alpha=0, you get the Delaunay triangulation and convex hull:

danschikore_0-1752758596250.png

As you increase alpha, you can get a hole in the middle:

danschikore_1-1752758679465.png

Increase further, and you can get shapes like this:

danschikore_2-1752758797292.png

But the output will not be a polygonal hull if the original samples do not include interior points.  I think this would require some additional post-processing to find the outer boundary polygon.

Names Default To Here( 1 );
x_matrix = [0.309016994374947, 0.470228201833979, 0.809016994374948, 0.760845213036123, 1, 0.760845213036123,
0.809016994374948, 0.470228201833979, 0.309016994374948, 0, -0.309016994374947, -0.470228201833978,
-0.809016994374948, -0.760845213036123, -1, -0.760845213036123, -0.809016994374948, -0.470228201833979,
-0.309016994374948, 0];
y_matrix = [0.951056516295153, 0.647213595499958, 0.587785252292473, 0.247213595499958, 0, -0.247213595499958,
-0.587785252292473, -0.647213595499958, -0.951056516295153, -0.8, -0.951056516295154, -0.647213595499958,
-0.587785252292473, -0.247213595499958, 0, 0.247213595499958, 0.587785252292473, 0.647213595499958,
0.951056516295153, 0.8];
t = Triangulation( x( x_matrix, y_matrix ) );
a = Alpha Shape( t );
a << Set Alpha( alpha = 0 );
Eval(
	Eval Expr(
		New Window( "alpha shape",
			Outline Box( "Alpha Shape Explorer",
				HListBox(TextBox("Alpha: "), slider = Slider Box( 0, 4, alpha )),
				graph = Graph Box(
					Frame Size( 300, 300 ),
					X Scale( -1, 1 ),
					Y Scale( -1, 1 ),
					Path( Expr( a << get hull path ) )
				)
			)
		)
	)
);
slider << Set Function(
	Function( {this},
		a << Set Alpha( alpha );
		Eval( Eval Expr( graph << Set Graphics Script( Path( Expr( a << Get Hull Path ) ) ) ) );
	)
);

View solution in original post

18 REPLIES 18
txnelson
Super User

Re: How to make closewise continuous polygon with matrix

I am not exactly sure what is the context of your need for a polygon, however, if you look in the Scripting Index

     Help=>Scripting Index

and then search on Polygon, you will see the definition and example of using the Polygon function.

Jim
Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

this is close:

x_matrix = [59, 60, 62, 64, 68, 70, 80, 118, 130, 182, 461, 678, 696, 700, 701, 701, 701];
y_matrix = [44.07, -44.31, 105.11, -66.88, 132.65, -88.02, -91.87, -104.49, 116.54, -106.6, -108.17, -55.48, -95.9, -93, -87.98, -87.47, -69.45];
t = Triangulation( x( x_matrix, y_matrix ) );
order = t << gethullpoints;
xs = x_matrix[order];
ys = y_matrix[order];
dt = As Table( xs || ys );
Graph Builder(
	Size( 669, 491 ),
	Show Control Panel( 0 ),
	Variables( X( :Col1 ), Y( :Col2 ) ),
	Elements( Line( X, Y, Legend( 7 ), Ordering( "Row Order" ) ), Points( X, Y, Legend( 8 ) ) )
);

Craige_Hales_0-1752695494108.png

Search the scripting index for "hull" and you'll find the alpha shape function as well. the Triangulation function can also tell you about points inside the hull and how they form a Delaunay triangulation. If you care about clockwise vs counter clockwise, https://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-cloc...

 

I'm at the limit of my understanding, but I'd be fascinated to learn more about what you are doing.

@danschikore 

 

Craige

Re: How to make closewise continuous polygon with matrix

Thanks for the example @Craige_Hales - alpha shapes are definitely interesting for cases like this, since @PhamBao mentioned non-convex solutions.  When the input is a polygon, the results might not be quite what you expect.  The example below demonstrates the use of alpha shapes on a set of points.  The alpha shape is a subset of the Delaunay triangulation, which could include points, edges, and triangles.  In JMP, the alpha shape is showing you the only the triangles.  For alpha=0, you get the Delaunay triangulation and convex hull:

danschikore_0-1752758596250.png

As you increase alpha, you can get a hole in the middle:

danschikore_1-1752758679465.png

Increase further, and you can get shapes like this:

danschikore_2-1752758797292.png

But the output will not be a polygonal hull if the original samples do not include interior points.  I think this would require some additional post-processing to find the outer boundary polygon.

Names Default To Here( 1 );
x_matrix = [0.309016994374947, 0.470228201833979, 0.809016994374948, 0.760845213036123, 1, 0.760845213036123,
0.809016994374948, 0.470228201833979, 0.309016994374948, 0, -0.309016994374947, -0.470228201833978,
-0.809016994374948, -0.760845213036123, -1, -0.760845213036123, -0.809016994374948, -0.470228201833979,
-0.309016994374948, 0];
y_matrix = [0.951056516295153, 0.647213595499958, 0.587785252292473, 0.247213595499958, 0, -0.247213595499958,
-0.587785252292473, -0.647213595499958, -0.951056516295153, -0.8, -0.951056516295154, -0.647213595499958,
-0.587785252292473, -0.247213595499958, 0, 0.247213595499958, 0.587785252292473, 0.647213595499958,
0.951056516295153, 0.8];
t = Triangulation( x( x_matrix, y_matrix ) );
a = Alpha Shape( t );
a << Set Alpha( alpha = 0 );
Eval(
	Eval Expr(
		New Window( "alpha shape",
			Outline Box( "Alpha Shape Explorer",
				HListBox(TextBox("Alpha: "), slider = Slider Box( 0, 4, alpha )),
				graph = Graph Box(
					Frame Size( 300, 300 ),
					X Scale( -1, 1 ),
					Y Scale( -1, 1 ),
					Path( Expr( a << get hull path ) )
				)
			)
		)
	)
);
slider << Set Function(
	Function( {this},
		a << Set Alpha( alpha );
		Eval( Eval Expr( graph << Set Graphics Script( Path( Expr( a << Get Hull Path ) ) ) ) );
	)
);
Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

@danschikore Thanks! I found this picture and first three paragraphs useful for understanding alpha shape: https://doc.cgal.org/latest/Alpha_shapes_2/

Here it is with some random points.

n=200;
x_matrix = j(n,1,randomuniform(-1,1));
y_matrix = j(n,1,randomuniform(-1,1));
t = Triangulation( x( x_matrix, y_matrix ) );
a = Alpha Shape( t );
a << Set Alpha( alpha = 0 );
Eval(
	Eval Expr(
		New Window( "alpha shape",
			Outline Box( "Alpha Shape Explorer",
				HListBox(TextBox("Alpha: "), slider = Slider Box( 0, 10, alpha )),
				graph = Graph Box(
					Frame Size( 300, 300 ),
					X Scale( -1, 1 ),
					Y Scale( -1, 1 ),
					Path( Expr( a << get hull path ) );
					marker(x_matrix,y_matrix)
				)
			)
		)
	)
);
slider << Set Function(
	Function( {this},
		a << Set Alpha( alpha );
		Eval( Eval Expr( graph << Set Graphics Script( Path( Expr( a << Get Hull Path ) );marker(x_matrix,y_matrix) ) ) );
	)
);

Craige
PhamBao
Level III

Re: How to make closewise continuous polygon with matrix

@danschikore  and @Craige_Hales @txnelson : appreciate all for your response and suggestion. All suggestions works for me

PhamBao
Level III

Re: How to make closewise continuous polygon with matrix

Hi @danschikore , @Craige_Hales and @Craige_Hales 
Based on your suggestion, it works for me. I also would like to ask some questions whether I could make script become more interactive. Since I am not really good at scripting, I would like to clarify what I want and hopefully I could get inputs and help from you guys
In my data table, I have 2 columns named "A" and "B" and then I use Triangulation to get convex hull of data points

Triangulation

 After getting convex hull, I draw polygon in box and copy frame content to graph builder

1. Is there any way that I could get convent hull and draw it directly in graph builder
2. If I would like to exclude some data points, how I could get instant convex hull updated in graph builder as well as to get new convex hull data points

PhamBao_0-1752904016674.png

PhamBao_1-1752904047810.png

 

 

There is my script:

dt= Open( "ww17_DATAALL.CSV");
 
tri = Triangulation( X( :A, :B), Y( :C ) );
 
 
// get contour around all data point
hulledge= tri << Get Hull Edges;
hullpoint =tri << Get Hull Points;
{xx, yy} = tri << Get Points();
tri2 = tri << Subset( tri << Get Hull Points ); // get data point of boundary
{tri2_xx, tri2_yy} = tri2 << Get Points();
show(tri2_xx);
show(tri2_yy);
 
//
ashape = Alpha Shape(tri);
ashape << Set Alpha(0.01);
{ax, ay} = ashape << Get Points();
atri = ashape << Get Triangles;
ashape2 = ashape<< Subset( ashape<< Get Hull Points ); // get data point of boundary
{ashape2_xx, ashape2_yy} = ashape2 << Get Points();
show(ashape2_xx);
show(ashape2_yy);
 
 
New Window( "Contour Seg Example",
g = Graph Box(
X Scale( Min( xx ) - .1, Max( xx ) + .1 ),
Y Scale( Min( yy ) - .1, Max( yy ) + .1 ),
Contour Seg(
tri,
[0, 400, 1000, 2000, 9000],
zColor( 5 + [64 32 0 16 48] ),
Transparency( [1, 1, 1, 1, 1] )
),
Shape Seg( {Path( ashape << Get Hull Path() )}, <<Set Color( "Red" ) ),
Shape Seg( {Path( tri << Get Hull Path() )}, <<Set Color( "Black" ) )
)
);
frame = g[FrameBox( 1 )];
fontobj = seg = (frame << Find Seg( Contour Seg( 1 ) ));
 
frame << Copy Frame Contents;
 
 
//graphbuilder
chartdisplay = dt << Graph Builder(
Size( 1011, 666 ),
Show Control Panel( 0 ),
Variables( X( :A ), Y( :B ) ),
Elements( Points( X, Y, Legend( 3 ) ), Smoother( X, Y, Legend( 4 ) ) ),
SendToReport(
Dispatch(
{},
"A",
ScaleBox,
{Min( Min( xx ) ), Max( Max( xx ) ), Inc( 100 ), Minor Ticks( 1 )}
),
Dispatch(
{},
"B",
ScaleBox,
{Min( min(yy) ), Max( Max(yy) ), Inc( 2 ), Minor Ticks( 1 )}
)
)
);
rbiv1 = chartdisplay << report;
framebox2 = rbiv1[Frame Box( 1 )];
 
frame << Copy Frame Contents;
framebox2 << Paste Frame Contents;
PhamBao
Level III

Re: How to make closewise continuous polygon with matrix

Hi @Craige_Hales  and @Craige_Hales  and @txnelson 

Right now, my script is working by your help.  I would like to ask another question about scripting since I am really good at in scripting.

 

In my data table, I have two columns called "FORCEDROPTIME_3" and "ACTUAL_MAXCHASEHOLDFORCE_4"

 

I uses code below to draw  convex hull around all data point

tri = Triangulation( X( :FORCEDROPTIME_3, :ACTUAL_MAXCHASEHOLDFORCE_4), Y( :ACTUALHEIGHTHOLDTIME_2 ) );// get contour around all data point
hulledge= tri << Get Hull Edges;
hullpoint =tri << Get Hull Points;
{xx, yy} = tri << Get Points();
tri2 = tri << Subset( tri << Get Hull Points ); // get data point of boundary
{tri2_xx, tri2_yy} = tri2 << Get Points();

 

 

Then I draw convex hull in the box and copy content frame to graph builder

New Window( "Contour Seg Example",
g = Graph Box(
X Scale( Min( xx ) - .1, Max( xx ) + .1 ),
Y Scale( Min( yy ) - .1, Max( yy ) + .1 ),
Contour Seg(
tri,
[0, 400, 1000, 2000, 9000],
zColor( 5 + [64 32 0 16 48] ),
Transparency( [1, 1, 1, 1, 1] )
),
Shape Seg( {Path( ashape << Get Hull Path() )}, <<Set Color( "Red" ) ),
Shape Seg( {Path( tri << Get Hull Path() )}, <<Set Color( "Black" ) )
)
);
frame = g[FrameBox( 1 )];
fontobj = seg = (frame << Find Seg( Contour Seg( 1 ) ));
 
frame << Copy Frame Contents;
 
 
//graphbuilder
chartdisplay = dt << Graph Builder(
Size( 1011, 666 ),
Show Control Panel( 0 ),
Variables( X( :FORCEDROPTIME_3 ), Y( :ACTUAL_MAXCHASEHOLDFORCE_4 ) ),
Elements( Points( X, Y, Legend( 3 ) ), Smoother( X, Y, Legend( 4 ) ) ),
SendToReport(
Dispatch(
{},
"FORCEDROPTIME_3",
ScaleBox,
{Min( Min( xx ) ), Max( Max( xx ) ), Inc( 100 ), Minor Ticks( 1 )}
),
Dispatch(
{},
"ACTUAL_MAXCHASEHOLDFORCE_4",
ScaleBox,
{Min( min(yy) ), Max( Max(yy) ), Inc( 2 ), Minor Ticks( 1 )}
)
)
);
rbiv1 = chartdisplay << report;
framebox2 = rbiv1[Frame Box( 1 )];
 
frame << Copy Frame Contents;
framebox2 << Paste Frame Contents;

The result is 
PhamBao_0-1752783496279.png

I have 2 questions;
1. Is there anyway that I could draw convex hull directly into graph builder?
2. In the graph builder chart, if I would like to exclude or remove data data points, How I could get new convex hull constantly updated in the graph. For example, if I use local filter of graph builder to filter some data points

--> how could I get new convex hull according to filtered data points 
--> how could I get X and Y matrix of new convex hull directly

Appreciate!

Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

sorry, the spam trap is aggressive today! I released both.

Craige
Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

maybe this

dt = Open( "$SAMPLE_DATA/Big Class.jmp" );

New Window( "hull test",
	Data Filter Context Box( // from the scripting index: how to make a data filter. the 'f' is needed.
		H List Box(
			f = dt << Data Filter( Local, Mode( Show( 1 ), Include( 1 ) ), Add Filter( columns( :age ) ) ),
			gb = dt << Graph Builder(
				Size( 660, 491 ),
				Show Control Panel( 0 ),
				Variables( X( :weight ), Y( :height ) ),
				Elements( Points( X, Y, Legend( 5 ) ) ), 

			)
		)
	)
);

Report( gb )[framebox( 1 )] << Add Graphics Script(
	// this script runs when the display needs to redraw.
	rows = f << getfilteredrows; // get the currently chosen rows from the filter
	If( Is Empty( rows ),
		rows = 0; // handle the 'nothing selected' case; 0 means 'all rows'
	);
	x_matrix = dt[rows, {weight}];
	y_matrix = dt[rows, {height}];
	t = Triangulation( x( x_matrix, y_matrix ) ); // from the current rows
	{x_matrix, y_matrix} = t << get points; // rearranged from input order!
	order = t << gethullpoints;
	xs = x_matrix[order |/ order[1]]; // repeat 1st point to close the loop
	ys = y_matrix[order |/ order[1]];
	Line( xs, ys );
);

@danschikore  - I think I made an error above when I didn't use <<getpoints with <<gethullpoints, even though it appeared to work. Using <<gethullpath makes it easier. 

Craige

Recommended Articles