Jump to content
Developer Wiki and Function Reference Links ×

Is 3D Poly Clockwise


Recommended Posts

There is a 2D call for "Is 2D Poly Clockwise"  ie GetObjectVariableBoolean(polyH,652);

 

There is no 3D equivalent as far as I can tell. Tried the following code but is unreliable. Has anyone managed to crack this problem with Vectorscript?

 

procedure test;
VAR
  polyH : HANDLE;
  x1,y1,z1,x2,y2,z2,x3,y3,z3,dval : REAL;
  v1,v2 : VECTOR;
  direction : STRING;

begin 
  polyH := fsactlayer;
  GetPolyPt3D(polyH,0,x1,y1,z1); {vertex 1}
  GetPolyPt3D(polyH,1,x2,y2,z2); {vertex 2}
  GetPolyPt3D(polyH,2,x3,y3,z3); {vertex 3}

  v1.x := x2-x1; v1.y := y2-y1; v1.z := z2-z1; {first edge}
  v2.x := x3-x2; v2.y := y3-y2; v2.z := z3-z2; {second edge}
  
  dval := DotProduct(unitvec(v1),unitvec(v2));
  if dval > 0 then direction := 'Clockwise'
  else direction := 'Anteclockwise';

  message(direction);
end;
run(test);

 

Link to comment
  • Marionette Maven

Here's the Python code that will potentially be used in a combo Is Clockwise node for both 2D and 3D inputs.

My testing so far shows this to be accurate.

Maybe it can be useful/translated into VS?

 

@Marionette.NodeDefinition
class Params(metaclass=Marionette.OrderedClass):
	# APPEARANCE
	this = Marionette.Node("Is Clockwise 2D/3D OPT")
	this.SetDescription("Determines if the polygon is clockwise oriented (works for both 2D and 3D polygons).")

	# INPUT PORTS
	poly = Marionette.PortIn(vs.Handle(0), "Polygon Handle")
	poly.SetDescription("A 2D or 3D polygon.")

	# OUTPUT PORTS
	isCW = Marionette.PortOut("Clockwise Orientation")
	isCW.SetDescription("True if the polygon is clockwise oriented, False otherwise.")

def RunNode(self):
	def is_clockwise(points):
		signed_area = sum(
			(points[i][0] * points[(i + 1) % len(points)][1] - points[(i + 1) % len(points)][0] * points[i][1])
			for i in range(len(points))
		)
		# Negative signed area indicates clockwise orientation
		return signed_area < 0

	# Input polygon handle
	hPoly = self.Params.poly.value

	# Validate input
	if hPoly == vs.Handle(0):
		self.Params.isCW.value = None
		return

	# Determine if the polygon is 2D or 3D
	numverts = vs.GetVertNum(hPoly)
	if numverts < 3:
		# Less than 3 vertices cannot form a valid polygon
		self.Params.isCW.value = None
		return

	# Collect vertices and project to 2D (ignore z-coordinate if 3D)
	if vs.GetTypeN(hPoly) == 25:  # 3D Polygon
		polygon_points = [vs.GetPolyPt3D(hPoly, i)[:2] for i in range(numverts)]
	else:  # 2D Polygon
		polygon_points = [vs.GetPolyPt(hPoly, i) for i in range(numverts)]

	# Determine orientation
	result = is_clockwise(polygon_points)

	# Assign output
	self.Params.isCW.value = result

 

Link to comment

Thanks Marissa. I did think of ditching the Z value as your code but was worried about the instance of a 3D polygon face aligned truely vertical. Will give it a try.

The reason for needing this check, is when a 3D object is converted to 3D polygons, I want to check orientation and set accordingly and in the instance of an import that has mixed orientations I want all 3D polygons to have the same orientation ie facing IN or OUT

Link to comment

I've just had a eurika moment. I manually reverse a polygon/polyline direction by looping through the vertices and rebuilding. A simpler solution is below which seem to work fine, although the first vertex seem to change which mimics the "Reverse Direction" button in the OIP for polygons.

 

procedure test;

procedure reversepoly(polyH : HANDLE);
begin
  SetObjectVariableBoolean(polyH,652,NOT (GetObjectVariableBoolean(polyH,652)));
end;

begin 
  reversepoly(fsactlayer);
end;
run(test);

 

Link to comment
Posted (edited)

I think I have come up with a vectorscript version of "is_clockwise" for 3D polygons only

 

I checked the python output from

   (points[i][0] * points[(i + 1) % len(points)][1] - points[(i + 1) % len(points)][0] * points[i][1])

 

with

for i in range(10):
    msg = str(i)+' '+str((i + 1) % 10)
    vs.AlrtDialog(msg)

 

which seemed to return 0 1, 1 2, 2 3 etc   from points[i][0] and points[(i + 1) % len(points)]

 

Edit: forgot the polygon closing edge

 

 

procedure test;

function is_clockwise(polyH : HANDLE) : BOOLEAN;
VAR
  i,vnum : INTEGER;
  p1,p2,p3 : POINT;
  signedarea,val : REAL;
  z1 : REAL;

begin
  signedarea := 0;
  vnum := GetVertNum(polyH);

  GetPolyPt3D(polyH,0,p1.x,p1.y,z1);
  p3 := p1; {store first vertex}

  for i := 1 to vnum-1 do begin
	GetPolyPt3D(polyH,i,p2.x,p2.y,z1);
	val := (p1.x * p2.y) - (p2.x * p1.y);
	p1 := p2;
	signedarea := signedarea + val;
  end;

  {closing edge}
  p2 := p3;
  val := (p1.x * p2.y) - (p2.x * p1.y);
  signedarea := signedarea + val;
  
  is_clockwise := (signedarea < 0);
end;

begin 
  message('Is clockwise ',is_clockwise(FSActLayer));
end;
run(test);

 

Edited by BillW
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...