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

18 REPLIES 18
PhamBao
Level III

Re: How to make closewise continuous polygon with matrix

Hi @Craige_Hales ,

Thank for your help. It works

I try to edit the code a little bit, but it does work. Is there anyway that I could add slider into 

Add Graphics Script

so that I could get value from slider as variable

Thanks

Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

I think the script in our other thread does exactly that.
A slider box doesn't go *in* the graphics script. It is a display box that is in the new window. The variable that the slider box sets can be referenced in the script.
Craige
PhamBao
Level III

Re: How to make closewise continuous polygon with matrix

Hi @Craige_Hales,

If I get points  ashape2_xx,ashape2_yy from ashape2 = ashape<< Subset( ashape<< Get Hull Points ); // get data point of boundary {ashape2_xx, ashape2_yy} = ashape2 << Get Points(), then I use polygon(ahsape2_xx, ashape2_yy) instead of Path(), polygon is not continuous
Do you know how I could sort ashape2_xx anshape2_yy, so that I could draw continuous polygon from Polygon() syntax

Thank a lot, 

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();

 

Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

It might be worth backing up and describing what you need to do (perhaps in a new question). 

I've played with alpha shape for a while and think I understand what you are fighting with: 

Both the <<get hull path and <<get hull points return a bunch of segments in scrambled order. Path covers up the problem by drawing all the segments using a move/draw for each; this makes 1 or more visual polygons, but not with a sequential border that works for filling a polygon. The points version returns the same data (as indexes into the <<getpoints data), and it can be used just like the path version...but again, not for filling.

If there is only a single outline for one polygon, it isn't too hard to sort the segments into a nice loop. If there are multiple polygons that don't share vertices, it is only a little harder. But if there are shared points between polygons the problem seems quite hard. If you turn the alpha up much, there will often be multiple polygons sharing points.

If you want to experiment with sorting the polygon edges into a loop, consider using a JSL list to hold the indexes. You can put the first edge in the list something like this

plist = {};
ie = 1; // index to an edge
from = hullEdges[ie, 1];
dest = hullEdges[ie, 2];
Insert Into( plist, from ); // append to empty list
Insert Into( plist, dest );

you can then walk through the hulledge matrix looking for edges that connect at the beginning or end of plist:

					found = 1;
					While( found,
						found = 0;
						For( je = 1, je <= ne, je += 1,
							testfrom = hullEdges[je, 1];
							testdest = hullEdges[je, 2];
								If(
									from == testdest, 
										// add to left end
										Insert Into( plist, testfrom, 1 );
										from = testfrom;
										pointCounts[testfrom] -= 1;
										pointCounts[testdest] -= 1;
										found = 1;//
								, /*else */ dest == testfrom, //
										// add to right end
										Insert Into( plist, testdest );
										dest = testdest;
										pointCounts[testfrom] -= 1;
										pointCounts[testdest] -= 1;
										found = 1;
								);
							);
						);
					);

If you successfully collect the indexes to the points, you can make a polygon, something like this:

// {x2, y2} = ashape2 << getPoints;
					// gather the polygon x and y matrices
					idx = plist;
					xdata = x2[idx];
					ydata = y2[idx];
					Transparency( .2 );
					Fill Color( HLS Color( (ie + 1) / ne, .5, 1 ) );
					Polygon( xdata, ydata, <<fill( 1 ) );

you might want something like this to check if there are points used by more than two edges:

			np = ashape2 << getnpoints;
			// most points are in 2 segs. some are in 4 segs.
			pointCounts = J( np, 1, 0 );
			If( N Rows( hullEdges ) > 0,pointCounts[hullEdges]++);
			
			If( !All( pointCounts == 2 ),
				Print( "too complicated" )
			);

That middle statement uses a 2-d matrix to index a matrix of counts and increment the counts 0, 2, or 4 times.

if you have multiple polygons, you might need to keep up with which points have been used already and wrap another JSL loop around your code to find a new starting point. 

Craige
PhamBao
Level III

Re: How to make closewise continuous polygon with matrix

Hi @Craige_Hales , 
Thank your instruction. I try to follow your instruction to create my code. Since I'm not good at coding, what is 

pointCounts

Could you give me a full code? 
Sincerely

Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

The "J" function creates a matrix, so
pointCounts = J( np, 1, 0 );
Makes a np rows by 1 col matrix initialized to 0.
The next statement,
If( N Rows( hullEdges ) > 0,
pointCounts[hullEdges]++)
Checks if there are any edges in hulledges (also a matrix with 2 cols for the from and to vertices). If so, every point index in hulledges is used as an index into pointcounts. Most points occur twice (connecting two edges ), resulting in a count of 2. Some occur 4 if two polys touch at that point. Some occur 0 times in hulledges if they are not in a poly with edges.
You'll need to write and maintain this code; this community, the scripting index in the help menu, and the jsl scripting guide are great resources for the low level parts.
Craige
Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

You don't have to use the pointcounts at all if you know there is exactly one polygon. You can comment out those statements to get started. 

When your data makes multiple polygons that touch, you might want to know. The pointcounts will help you write the code to handle that case.

The 4th block of code should be first to set up the total counts if you need them.

The 2nd block is an example of using the counts by decrementing them after they are used. You might do that to  help figure out which points are still not used up when ordering the edges of the polygons.

In the video, way above, you can see a frame with islands and holes. I've colored it by hand, maybe correctly. Blue is "in", tan is "out". The hard part will be dealing with polygons like 1 and 2.

Craige_Hales_1-1754260256546.png

If you never push the alpha parameter far enough to make islands and holes, then you only have a single continuous outline and the code above should sort it so it works with the polygon command.

 

Craige
PhamBao
Level III

Re: How to make closewise continuous polygon with matrix

Hi Craige_Hales,
I try to use your code as reference and apply it into my own

 
 


dt= Open( "C:\Users\lamquocb\OneDrive - Intel Corporation\Desktop\Python Script\Regression\RPLP682\trial.jmp");



//
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();

////////////

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();


hullEdges=ashape << Get Hull Edges;
plist = {};
ie = 1; // index to an edge
from = hullEdges[ie, 1];
dest = hullEdges[ie, 2];
Insert Into( plist, from ); // append to empty list
Insert Into( plist, dest );
found = 1;
					While( found,
						found = 0;
						For( je = 1, je <= N Items(hullEdges), je += 1,
							testfrom = hullEdges[je, 1];
							testdest = hullEdges[je, 2];
								If(
									from == testdest, 
										// add to left end
										Insert Into( plist, testfrom, 1 );
										from = testfrom;
										
										found = 1;//
								, /*else */ dest == testfrom, //
										// add to right end
										Insert Into( plist, testdest );
										dest = testdest;
									
										found = 1;
								);
							);
						);
					
However I got the error : 
invalid subscript (must be number or list of numbers) in access or evaluation of 'hullEdges[ /*###*/je,1]' , hullEdges[/*###*/je, 1]

Typically if I actual number into hullEdge[1,2] as an example instead of hullEdges[je, 2], I got the result returns

Do you have any idea to resolve the issue?




Craige_Hales
Super User

Re: How to make closewise continuous polygon with matrix

@Audrey_Shull  

JMP's error message makes the problem hard to understand. it should say

"the first index to hulledges[ 33, 2 ] is 34 and out of bounds"

 

nitems returns the total number of elements, not the number of rows.

 

change

For( je = 1, je <= N Items(hullEdges), je += 1,

to

For( je = 1, je <= N Rows(hullEdges), je += 1,

 

Craige

Recommended Articles