Libraries & objects
About Archicad and BIMcloud libraries, their management and migration, objects and other library parts, etc.

intersection point of two lines

Hmooslechner
Moderator
i try to get the intersection point of two lines:

line2 x11, y11, x12, x12
line2 x21, y21, x22, y22

is there a simple solution for this?

I am not so settlet in vector mathematics.. and tried it over the angles but my brain now is boiling...

I hope someone can help - thanks forwarding..
AC5.5-AC27EduAut, PC-Win10, MacbookAirM1, MacbookM1Max, Win-I7+Nvidia
14 REPLIES 14
Hmooslechner
Moderator
Meanwhile i found this:

http://www.graphisoft.com/ftp/techsupport/documentation/developer_docs/BasicLibraryDoc/16/Window-Mac...

But my Archicad cant find the Macro - how can i test if archicad has loaded the apx?

And does anybody know a direct GDL-Anser to this? Without the polygon opreation macro?
AC5.5-AC27EduAut, PC-Win10, MacbookAirM1, MacbookM1Max, Win-I7+Nvidia
Pertti Paasky
Expert
Hi ,Hmooslechner
You can find formulas and other staff for example here
http://paulbourke.net/geometry/pointlineplane/
- be cool -
- AC-24 FIN - WIN 10 - HP Zbook -
“A winner is just a loser who tried one more time.”
George M. Moore, Jr.
Anonymous
Not applicable
Hello,

Here is a line-line intersection object, which is using
built-in polygon operations macros.
Anonymous
Not applicable
Here is a preview, hope the object works.
Frank Beister
Moderator
After a standard installation of AC 16 (GER) the basic library seems not to be part of the national library. At least the PolyOperations makro is not available for custom designed objects.
AFAIR with update to ArchiCAD 14 this has changed. I have asked for this in the past, but haven't got any answer.
Can anyone confirm this general lack or are the basic library macros available in other localised versions? Can others download and use Juhas example object in ArchiCAD 16?
bim author since 1994 | bim manager since 2018 | author of selfGDL.de | openGDL | skewed archicad user hall of fame | author of bim-all-doors.gsm
Anonymous
Not applicable
Donnerwetter!

It is working in ArchiCAD 16 FIN.

Here is the polygon operations macro in version 16 if someone needs it.

Hope GS does not sue me for distributing warez here
Anonymous
Not applicable
...and here is the code (master script) if you want to make a macro of your own.




EPS = 0.0001

OPERATION_CONVERT_POLYGON_AC_TO_GDL		= 1
OPERATION_POINT_INSIDE_POLYGON			= 2
OPERATION_LINE_LINE_INTERSECTION		= 3
OPERATION_SEGMENT_SEGMENT_INTERSECTION	= 4
OPERATION_INTERSECT_POLYGONS			= 5
OPERATION_CALCULATE_POLYGON_AREA		= 6
OPERATION_REVERSE_POLYGON				= 7

INPUT_NO			 = 0
INPUT_FROM_PARAMETER = 1
INPUT_FROM_GDL_STACK = 2

OUTPUT_TO_PARAMETER = 1
OUTPUT_TO_GDL_STACK = 2

! ==============================================================================

bCalledFromScript = 0

if opcode = OPERATION_CONVERT_POLYGON_AC_TO_GDL		then 100	! Convert polygon: AC polygon -> GDL polygon
if opcode = OPERATION_POINT_INSIDE_POLYGON			then 200	! Point inside polygon check
if opcode = OPERATION_LINE_LINE_INTERSECTION		then 300	! Line-Line intersection
if opcode = OPERATION_SEGMENT_SEGMENT_INTERSECTION	then 400	! Segment-Segment intersection
if opcode = OPERATION_INTERSECT_POLYGONS			then 500	! Intersect polygons
if opcode = OPERATION_CALCULATE_POLYGON_AREA		then 600	! Calculate polygon area
if opcode = OPERATION_REVERSE_POLYGON				then 700	! Reverse polygon 

end



100:
! ==============================================================================
! Convert polygon: AC polygon -> GDL polygon
!	OPERATION_CONVERT_POLYGON_AC_TO_GDL
! ==============================================================================
! Input:
!	srcPolygon1:	input source of polygon 1 (INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	polygon1:		input polygon
!	result:			output result (OUTPUT_TO_PARAMETER, OUTPUT_TO_GDL_STACK)
!	GDL stack:		coordX[1], coordY[1], arc[1], ...
!
! Output:
!	polygon2:		output polygon
!	GDL stack:		coordX[1], coordY[1], status[1], ...
! ==============================================================================

gosub 101

if result = OUTPUT_TO_GDL_STACK then end
end polygon2

101:
	if srcPolygon1 = INPUT_FROM_PARAMETER then
		numPnts = vardim1(polygon1)
	endif
	if srcPolygon1 = INPUT_FROM_GDL_STACK then
		numPnts = nsp/3
	endif
	ac2gdl_lpa = 0
	ac2gdJ = 1

	for ac2gdlI = 1 to numPnts
		if srcPolygon1 = INPUT_FROM_PARAMETER then
			ac2gdl_px = polygon1[ac2gdlI][1]
			ac2gdl_py = polygon1[ac2gdlI][2]
			ac2gdl_pa = polygon1[ac2gdlI][3]
		endif
		if srcPolygon1 = INPUT_FROM_GDL_STACK then
			ac2gdl_px = get(1)
			ac2gdl_py = get(1)
			ac2gdl_pa = get(1)
		endif

		if ac2gdlI = 1 then
			ac2gdl_spx = ac2gdl_px
			ac2gdl_spy = ac2gdl_py
		endif

		if abs(ac2gdl_lpa) > EPS then
			ac2gdl_mx = (ac2gdl_px + ac2gdl_lpx) / 2
			ac2gdl_my = (ac2gdl_py + ac2gdl_lpy) / 2
			ac2gdl_ratio = 1 / 2 / tan (ac2gdl_lpa / 2)

			ac2gdl_cx = ac2gdl_mx - ac2gdl_ratio * (ac2gdl_py - ac2gdl_lpy)	! Arc center
			ac2gdl_cy = ac2gdl_my + ac2gdl_ratio * (ac2gdl_px - ac2gdl_lpx)

			if result = OUTPUT_TO_PARAMETER then
				polygon2[ac2gdJ][1] = ac2gdl_cx
				polygon2[ac2gdJ][2] = ac2gdl_cy
				polygon2[ac2gdJ][3] = 900
				ac2gdJ = ac2gdJ + 1

				polygon2[ac2gdJ][1] = 0
				polygon2[ac2gdJ][2] = ac2gdl_lpa
				polygon2[ac2gdJ][3] = 4001
				ac2gdJ = ac2gdJ + 1
			endif
			if result = OUTPUT_TO_GDL_STACK then
				put ac2gdl_cx,	ac2gdl_cy,	900,
					0,			ac2gdl_lpa,	4001
			endif
		endif

		if ac2gdlI>1 & abs(ac2gdl_spx - ac2gdl_px) < EPS & abs(ac2gdl_spy - ac2gdl_py) < EPS then
			if result = OUTPUT_TO_PARAMETER then
				polygon2[ac2gdJ][1] = ac2gdl_px
				polygon2[ac2gdJ][2] = ac2gdl_py
				polygon2[ac2gdJ][3] = -1
				ac2gdJ = ac2gdJ + 1
			endif
			if result = OUTPUT_TO_GDL_STACK then
				put ac2gdl_px, ac2gdl_py, -1
			endif
		else
			if result = OUTPUT_TO_PARAMETER then
				polygon2[ac2gdJ][1] = ac2gdl_px
				polygon2[ac2gdJ][2] = ac2gdl_py
				polygon2[ac2gdJ][3] = 1
				ac2gdJ = ac2gdJ + 1
			endif
			if result = OUTPUT_TO_GDL_STACK then
				put ac2gdl_px, ac2gdl_py, 1
			endif
		endif

		ac2gdl_lpx = ac2gdl_px
		ac2gdl_lpy = ac2gdl_py
		ac2gdl_lpa = ac2gdl_pa
	next ac2gdlI
return


200:
! ==============================================================================
! Point inside polygon check
!	OPERATION_POINT_INSIDE_POLYGON
! ==============================================================================
! Input:
!	srcPolygon1:	input source of polygon 1 (INPUT_NO, INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	polygon1:		input polygon 1
!	srcPolygon2:	input source of polygon 2 (INPUT_NO, INPUT_FROM_PARAMETER)
!	polygon2:		input polygon 2
!	srcPoint:		input source of point (INPUT_NO, INPUT_FROM_PARAMETER)
!	pntX:			point X
!	pntY:			point Y
!	result:			output result (OUTPUT_TO_PARAMETER, OUTPUT_TO_GDL_STACK)
!	GDL stack:		coordX[1], coordY[1], arc[1], ...
!
! Output:
!	ret:			output status
!						0: Error
!						1: Inside
!						2: Outside
!						3: On Edge
!						4: On Point
!	GDL stack:		[1]: output status
! ==============================================================================
! Remarks:
!	The polygon can be convex or concave too
!	It works with polygons containing straight segments only
!	The polygon can't contains holes
!	The input polygon from polygon1 or from polygon2 must be closed
!	The input polygon from GDL stack can be opened (it is closed automaticaly)
! ==============================================================================

gosub 201

if result = OUTPUT_TO_GDL_STACK then
	put ret
	end
endif
end ret

201:
	pipNumPnts = 0

	if srcPoint = INPUT_FROM_GDL_STACK then
		pntX = get(1)
		pntY = get(1)
	endif

	if srcPolygon1 = INPUT_FROM_GDL_STACK then
		dim pipPoly[][3]

		pipNumPnts = nsp/3
		for pipI=1 to pipNumPnts
			pipPoly[pipI][1] = get(1)
			pipPoly[pipI][2] = get(1)
			pipPoly[pipI][3] = get(1)
		next pipI
		if abs(pipPoly[pipNumPnts][1] - pipPoly[1][1]) > EPS | abs(pipPoly[pipNumPnts][2] - pipPoly[1][2]) > EPS then
			pipNumPnts = pipNumPnts + 1
			pipPoly[pipNumPnts][1] = pipPoly[1][1]	! Close polygon
			pipPoly[pipNumPnts][2] = pipPoly[1][2]
		endif
	endif
	if srcPolygon1 = INPUT_FROM_PARAMETER & srcPolygon2 = INPUT_NO then
		pipNumPnts = vardim1(polygon1)
	endif
	if srcPolygon1 = INPUT_NO & srcPolygon2 = INPUT_FROM_PARAMETER then
		pipNumPnts = vardim1(polygon2)
	endif
	if pipNumPnts = 0 then return	! Error

	ret = 0		! Error
	pipEnd = 0
	pipIntersection = 0

	if srcPolygon1 = INPUT_FROM_GDL_STACK then
		pipX0 = pipPoly[pipNumPnts - 1][1]
		pipY0 = pipPoly[pipNumPnts - 1][2]
		pipX1 = pipPoly[1][1]
		pipY1 = pipPoly[1][2]
	endif
	if srcPolygon1 = INPUT_FROM_PARAMETER & srcPolygon2 = INPUT_NO then
		pipX0 = polygon1[pipNumPnts - 1][1]
		pipY0 = polygon1[pipNumPnts - 1][2]
		pipX1 = polygon1[1][1]
		pipY1 = polygon1[1][2]
	endif
	if srcPolygon1 = INPUT_NO & srcPolygon2 = INPUT_FROM_PARAMETER then
		pipX0 = polygon2[pipNumPnts - 1][1]
		pipY0 = polygon2[pipNumPnts - 1][2]
		pipX1 = polygon2[1][1]
		pipY1 = polygon2[1][2]
	endif

	for pipI=1 to pipNumPnts - 1

		! Point on polygon vertex test
		if abs(pipX1 - pntX) < EPS & abs(pipY1 - pntY) < EPS then
			ret		= 4					! OnPoint
			pipI	= pipNumPnts - 1	! Force end loop
			pipEnd	= 1
		endif

		! Point on edge test
		pipSegLength = sqr((pipX0 - pipX1)^2 + (pipY0 - pipY1)^2)
		if pipSegLength > EPS & not(pipEnd) then
			if abs(abs((pipY0 - pipY1) * (pntX - pipX1) - (pipX0 - pipX1) * (pntY - pipY1)) / pipSegLength) < EPS then
				ret		= 3					! OnEdge
				pipEnd	= 1
			endif
		endif

		if srcPolygon1 = INPUT_FROM_GDL_STACK then
			pipX2 = pipPoly[pipI + 1][1]
			pipY2 = pipPoly[pipI + 1][2]
		endif
		if srcPolygon1 = INPUT_FROM_PARAMETER & srcPolygon2 = INPUT_NO then
			pipX2 = polygon1[pipI + 1][1]
			pipY2 = polygon1[pipI + 1][2]
		endif
		if srcPolygon1 = INPUT_NO & srcPolygon2 = INPUT_FROM_PARAMETER then
			pipX2 = polygon2[pipI + 1][1]
			pipY2 = polygon2[pipI + 1][2]
		endif

		srcLine1 = INPUT_FROM_PARAMETER
		line1X1 = pipX1
		line1Y1 = pipY1
		line1X2 = pipX2
		line1Y2 = pipY2

		srcLine2 = INPUT_FROM_PARAMETER
		line2X1 = pntX
		line2Y1 = pntY
		line2X2 = pntX + 1000
		line2Y2 = pntY

		gosub 401	! Segment-Segment intersection
					! Result: state, cx,cy

		if state = 3 then
			if abs(line1X2 - cx) > EPS | abs(line1Y2 - cy) > EPS then
				if abs(line1X1 - cx) < EPS & abs(line1Y1 - cy) < EPS then
					if sgn(pipY0 - pntY) <> sgn(pipY2 - pntY) then
						pipIntersection = pipIntersection + 1
					endif
				else
					pipIntersection = pipIntersection + 1
				endif
			endif
		endif


		pipX0 = pipX1
		pipY0 = pipY1

		pipX1 = pipX2
		pipY1 = pipY2
	next pipI

	if pipEnd then return	! Already have valid result

	if (pipIntersection % 2 = 0) then	! Outside
		ret = 2
		return
	else	! Inside
		ret = 1
		return
	endif
return


300:
! ==============================================================================
! Line - Line intersection
! ==============================================================================
! Input:
!	srcLine1:		input source of line 1 (INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	line1X1:		line1 startpoint X
!	line1Y1:		line1 startpoint Y
!	line1X2:		line1 endpoint X
!	line1Y2:		line1 endpoint Y
!	srcLine2:		input source of line 2 (INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	line2X1:		line2 startpoint X
!	line2Y1:		line2 startpoint Y
!	line2X2:		line2 endpoint X
!	line2Y2:		line2 endpoint Y
!	result:			output result (OUTPUT_TO_PARAMETER, OUTPUT_TO_GDL_STACK)
!	GDL stack:		line1X1, line1Y1, line1X2, line1Y2, ...
!
! Output:
!	ret:			output status
!						 0: no intersection, parallel lines
!						 1: lines are intersects
!	cx:				intersection point X
!	cy:				intersection point Y
!	GDL stack:		[1]: output status
!					[2]: intersection point X
!					[3]: intersection point Y
! ==============================================================================

gosub 301
if result = OUTPUT_TO_GDL_STACK then
	put state, cx,cy
	end
endif
end state, cx,cy


301:
	if srcLine1 = INPUT_FROM_GDL_STACK then
		line1X1 = GET(1): line1Y1 = GET(1)	! S1 segment
		line1X2 = GET(1): line1Y2 = GET(1)
	endif
	if srcLine2 = INPUT_FROM_GDL_STACK then
		line2X1 = GET(1): line2Y1 = GET(1)	! S2 segment
		line2X2 = GET(1): line2Y2 = GET(1)
	endif

	lliDiv = (line1X1-line1X2) * (line2Y1-line2Y2) - (line1Y1-line1Y2) * (line2X1-line2X2)

	if abs(lliDiv) > EPS then
		! Intersection

		temp1 = line1X1 * line1Y2 - line1Y1 * line1X2
		temp2 = line2X1 * line2Y2 - line2Y1 * line2X2

		tempx = temp1 * (line2X1-line2X2) - (line1X1-line1X2) * temp2
		tempy = temp1 * (line2Y1-line2Y2) - (line1Y1-line1Y2) * temp2

		state = 1
		cx = (tempx / lliDiv)
		cy = (tempy / lliDiv)
	else
		! No Intersection
		state = 0
		cx = 0
		cy = 0
	endif
return




400:
! ==============================================================================
! Segment - Segment intersection
! ==============================================================================
! Input:
!	srcLine1:		input source of line 1 (INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	line1X1:		line1 startpoint X
!	line1Y1:		line1 startpoint Y
!	line1X2:		line1 endpoint X
!	line1Y2:		line1 endpoint Y
!	srcLine2:		input source of line 2 (INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	line2X1:		line2 startpoint X
!	line2Y1:		line2 startpoint Y
!	line2X2:		line2 endpoint X
!	line2Y2:		line2 endpoint Y
!	result:			output result (OUTPUT_TO_PARAMETER, OUTPUT_TO_GDL_STACK)
!	GDL stack:		line1X1, line1Y1, line1X2, line1Y2, ...
!
! Output:
!	ret:			output status
!						-1: no intersection, segments is not paralel
!						 0: no intersection, parallel segments
!						 1: intersection point lies on S1 segment, but not lies on S2
!						 2: intersection point lies on S2 segment, but not lies on S1
!						 3: intersection point lies on both segments
!	cx:				intersection point X
!	cy:				intersection point Y
!	GDL stack:		[1]: output status
!					[2]: intersection point X
!					[3]: intersection point Y
! ==============================================================================

gosub 401
if result = OUTPUT_TO_GDL_STACK then
	put state, cx,cy
	end
endif
end state, cx,cy

401:
	if srcLine1 = INPUT_FROM_GDL_STACK then
		line1X1 = GET(1): line1Y1 = GET(1)	! S1 segment
		line1X2 = GET(1): line1Y2 = GET(1)

		srcLine1 = INPUT_FROM_PARAMETER
	endif
	if srcLine2 = INPUT_FROM_GDL_STACK then
		line2X1 = GET(1): line2Y1 = GET(1)	! S2 segment
		line2X2 = GET(1): line2Y2 = GET(1)

		srcLine2 = INPUT_FROM_PARAMETER
	endif

	gosub 301	! Intersection of Line - Line

	if state then
		state = 0

		if abs(line1X1 - line1X2) < EPS then
			if (line1Y1-EPS <= cy & cy <= line1Y2+EPS) | (line1Y1+EPS >= cy & cy >= line1Y2-EPS) then state = 1
		else
			if (line1X1-EPS <= cx & cx <= line1X2+EPS) | (line1X1+EPS >= cx & cx >= line1X2-EPS) then state = 1
		endif
		if abs(line2X1 - line2X2) < EPS then
			if (line2Y1-EPS <= cy & cy <= line2Y2+EPS) | (line2Y1+EPS >= cy & cy >= line2Y2-EPS) then state = state + 2
		else
			if (line2X1-EPS <= cx & cx <= line2X2+EPS) | (line2X1+EPS >= cx & cx >= line2X2-EPS) then state = state + 2
		endif

		if state = 0 then state = -1
	endif
return



500:
! ==============================================================================
! Intersect Polygons
!	OPERATION_INTERSECT_POLYGONS
! ==============================================================================
!	opmethod:		contour staus handling method
!						0: edges with original status
!						1: set staus 0 (invisible) for all edges
!						2: set staus 1 (visible) for all edges
!						3: edges from polygon1 with 1, edges from polygon2 with 0 status
!						4: edges from polygon1 with 0, edges from polygon2 with 1 status
!						5: intersection point list
!	srcPolygon1:	input source of polygon 1 (INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	polygon1:		input polygon 1
!	srcPolygon2:	input source of polygon 2 (INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	polygon2:		input polygon 2
!	result:			output result (OUTPUT_TO_PARAMETER, OUTPUT_TO_GDL_STACK)
!
! Output:
!	resPoly:		output polygon
!	GDL stack:		coordX[1], coordY[1], status[1], ...
! ==============================================================================

dim resPoly[][3]

gosub 501
if result = OUTPUT_TO_GDL_STACK then
	for i=1 to vardim1(resPoly)
		put resPoly[1],
			resPoly[2],
			resPoly[3]
	next i
	end
endif
end resPoly


501:
	statusOriginal = (opmethod = 0)
	statusPolygon1 = (opmethod = 2 | opmethod = 3) * edgeAttribute
	statusPolygon2 = (opmethod = 2 | opmethod = 4) * edgeAttribute

	if srcPolygon1 = INPUT_FROM_PARAMETER then
		numPnts1 = vardim1(polygon1)
	endif
	if srcPolygon1 = INPUT_FROM_GDL_STACK then
		numPnts1 = nsp/3
		for i=1 to numPnts1
			polygon1[1] = get(1)
			polygon1[2] = get(1)
			polygon1[3] = get(1)
		next i
	endif
	if abs(polygon1[1][1] - polygon1[numPnts1][1]) > EPS | abs(polygon1[1][2] - polygon1[numPnts1][2]) > EPS then
		numPnts1 = numPnts1 + 1
		polygon1[numPnts1][1] = polygon1[1][1]	! Close polygon1
		polygon1[numPnts1][2] = polygon1[1][2]
		polygon1[numPnts1][3] = -1
	endif

	if srcPolygon2 = INPUT_FROM_PARAMETER then
		numPnts2 = vardim1(polygon2)
	endif
	if srcPolygon2 = INPUT_FROM_GDL_STACK then
		numPnts2 = nsp/3
		for i=1 to numPnts2
			polygon2[1] = get(1)
			polygon2[2] = get(1)
			polygon2[3] = get(1)
		next i
	endif
	if abs(polygon2[1][1] - polygon2[numPnts2][1]) > EPS | abs(polygon2[1][2] - polygon2[numPnts2][2]) > EPS then
		numPnts2 = numPnts2 + 1
		polygon2[numPnts2][1] = polygon2[1][1]	! Close polygon2
		polygon2[numPnts2][2] = polygon2[1][2]
		polygon2[numPnts2][3] = -1
	endif

	srcPoint	= INPUT_FROM_PARAMETER
	srcPolygon1 = INPUT_NO
	srcPolygon2 = INPUT_FROM_PARAMETER
	pntX = polygon1[1][1]
	pntY = polygon1[1][2]

	gosub 201		! Check inside
					! Result: ret

	bInside = (ret = 1 | ret = 3)	! Inside or OnEdge

	srcPolygon1 = INPUT_FROM_PARAMETER
	srcPolygon2 = INPUT_NO
	gosub 601		! Calculate area of polygon1
					! Result: area
	if area < 0 then
		gosub 701		! Reverse polygon1
						! Result: polygon1
	endif

	srcPolygon1 = INPUT_NO
	srcPolygon2 = INPUT_FROM_PARAMETER
	gosub 601		! Calculate area of polygon2
					! Result: area
	if area < 0 then
		gosub 701		! Reverse polygon2
						! Result: polygon2
	endif


! Intersection poligons ========================================================

	contour = not(bInside)
	bClosed = 0
	id = 1
	ci = 1
	lastX = 0

	safetyCounter = 0
	safetyMax = numPnts1 + numPnts2

	do
		if contour then
			if ci >= numPnts2 then ci = 1

			srcPolygon1 = INPUT_FROM_PARAMETER
			srcPolygon2 = INPUT_NO

			pntX = polygon2[ci][1]
			pntY = polygon2[ci][2]
			pntS = polygon2[ci][3]
		else
			if ci >= numPnts1 then ci = 1

			srcPolygon1 = INPUT_NO
			srcPolygon2 = INPUT_FROM_PARAMETER

			pntX = polygon1[ci][1]
			pntY = polygon1[ci][2]
			pntS = polygon1[ci][3]
		endif

		srcPoint	= INPUT_FROM_PARAMETER

		gosub 201		! Check inside
						! Result: ret

		bInside = (ret = 1 | ret = 3)	! Inside or OnEdge

		if bInside then
			lastX = 0

			if statusOriginal then
				status = pntS
			else
				if contour then
					status = statusPolygon1
				else
					status = statusPolygon2
				endif
			endif

			if opmethod <> 5 then
				resPoly[id][1] = pntX
				resPoly[id][2] = pntY
				resPoly[id][3] = status!		pntS
			endif

			if id > 1 then
				if abs(resPoly[1][1] - pntX) < EPS & abs(resPoly[1][2] - pntY) < EPS then
					bClosed = 1
				endif
			endif

			id = id + 1
		endif


		! Look for crossing sectinos

		line1X1 = pntX
		line1Y1 = pntY
		if contour then
			line1X2 = polygon2[ci + 1][1]
			line1Y2 = polygon2[ci + 1][2]
		else
			line1X2 = polygon1[ci + 1][1]
			line1Y2 = polygon1[ci + 1][2]
		endif

		bCrossIt = 0
		bFinish = 0
		j = 1

		do
			if contour then
				line2X1 = polygon1[1]
				line2Y1 = polygon1[2]
				line2X2 = polygon1[j + 1][1]
				line2Y2 = polygon1[j + 1][2]
			else
				line2X1 = polygon2[1]
				line2Y1 = polygon2[2]
				line2X2 = polygon2[j + 1][1]
				line2Y2 = polygon2[j + 1][2]
			endif

			srcLine1 = INPUT_FROM_PARAMETER
			srcLine2 = INPUT_FROM_PARAMETER

			gosub 401	! Segment-Segment intersection
						! Result: state, cx,cy

			if state = 3 then

				if (abs(line2X2 - cx) < EPS & abs(line2Y2 - cy) < EPS) then
					state = 0
				endif

				if (abs(line1X1 - cx) < EPS & abs(line1Y1 - cy) < EPS) then
					state = 0
				endif

				if id > 1 then
					for k=2 to id-1
						if (abs(resPoly[1] - cx) < EPS & abs(resPoly[2] - cy) < EPS) then
							state = 0
							bInside = not(bInside)
						endif
					next k
				endif
			endif

			if state = 3 then

				bCrossIt = 1

				insertBefore = 0
				if lastX then
					lenThis = (pntX - cx)^2 + (pntY - cy)^2
					lenLast = (pntX - resPoly[id - 1][1])^2 + (pntY - resPoly[id - 1][2])^2

					if lenLast > lenThis then
						insertBefore = 1
					endif
				endif

				if statusOriginal then
					status = pntS
				else
					if contour then
						status = statusPolygon2
					else
						status = statusPolygon1
					endif
				endif

				if insertBefore then
					resPoly[id][1] = resPoly[id - 1][1]
					resPoly[id][2] = resPoly[id - 1][2]
					resPoly[id][3] = resPoly[id - 1][3]

					resPoly[id - 1][1] = cx
					resPoly[id - 1][2] = cy
					resPoly[id - 1][3] = status
				else
					resPoly[id][1] = cx
					resPoly[id][2] = cy
					resPoly[id][3] = status

					lastJ = j
				endif

				if id > 1 & not(insertBefore) then
					if abs(resPoly[1][1] - cx) < EPS & abs(resPoly[1][2] - cy) < EPS then
						bClosed = 1
					endif
				endif

				id = id + 1

				lancX = 0
				if id > 2 then
					if (abs((cy - pntY) * (resPoly[id - 2][1] - pntX) - (cx - pntX) * (resPoly[id - 2][2] - line1Y1)) / SQR((cx - pntX)^2 + (cy - pntY)^2)) < EPS then
						lancX = 1
					endif
				endif

				if not(lancX) then bCrossIt = 0


				if bInside | lancX then
					if insertBefore then
						ci = lastJ - 1
					else
						ci = j - 1
					endif
					contour = not(contour)

					bFinish = 1
				endif

				lastX = 1
			endif

			j = j + 1

			if contour then
				if j >= numPnts1 then bFinish = 1
			else
				if j >= numPnts2 then bFinish = 1
			endif

		while not(bCrossIt) & not(bFinish)

		ci = ci + 1

		safetyCounter = safetyCounter + 1
		if safetyCounter > safetyMax then bClosed = 1

	while not(bClosed)

	resPoly[1][3] = resPoly[id-1][3]	! Set correct status of the first edge
return




600:
! ==============================================================================
! Calculate polygon area
! ==============================================================================
! Input:
!	srcPolygon1:	input source of polygon 1 (INPUT_NO, INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	polygon1:		input polygon 1
!	srcPolygon2:	input source of polygon 2 (INPUT_NO, INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	polygon2:		input polygon 2
!	result:			output result (OUTPUT_TO_PARAMETER, OUTPUT_TO_GDL_STACK)
!	GDL stack:		coordX[1], coordY[1], arc[1], ...
!
! Output:
!	area:			area of polygon
!	GDL stack:		[1]: area of polygon
! ==============================================================================
! Remarks:
!	The input polygon must have closed
! ==============================================================================

gosub 601
if result = OUTPUT_TO_GDL_STACK then
	put area
	end
endif
end area

601:
	area = 0

	if srcPolygon1 = INPUT_FROM_PARAMETER & srcPolygon2 = INPUT_NO then
		tempNumPnts = vardim1(polygon1)

		for areaI=1 to tempNumPnts-1
			area = area + (polygon1[areaI+1][1] + polygon1[areaI][1]) * (polygon1[areaI+1][2] - polygon1[areaI][2]) * 0.5
		next areaI
		area = area + (polygon1[1][1] + polygon1[tempNumPnts][1]) * (polygon1[1][2] - polygon1[tempNumPnts][2]) * 0.5

		return
	endif

	if srcPolygon1 = INPUT_NO & srcPolygon2 = INPUT_FROM_PARAMETER then
		tempNumPnts = vardim1(polygon2)

		for areaI=1 to tempNumPnts-1
			area = area + (polygon2[areaI+1][1] + polygon2[areaI][1]) * (polygon2[areaI+1][2] - polygon2[areaI][2]) * 0.5
		next areaI
		area = area + (polygon2[1][1] + polygon2[tempNumPnts][1]) * (polygon2[1][2] - polygon2[tempNumPnts][2]) * 0.5

		return
	endif

	if srcPolygon1 = INPUT_FROM_GDL_STACK | srcPolygon2 = INPUT_FROM_GDL_STACK then
		tempNumPnts = nsp/3

		areaLX = get(1)	! Last point
		areaLY = get(1)
		areaFX = areaLX	! First point
		areaFY = areaLY

		for areaI=1 to tempNumPnts-1
			areaX = get(1)
			areaY = get(1)
			area = area + (areaX + areaLX) * (areaY - areaLY) * 0.5
			
			areaLX = areaX
			areaLY = areaY
		next areaI
		area = area + (areaFX + get(1)) * (areaFY - get(1)) * 0.5

		return
	endif
return


700:
! ==============================================================================
! Reverse polygon
! ==============================================================================
! Input:
!	srcPolygon1:	input source of polygon 1 (INPUT_NO, INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	polygon1:		input polygon 1
!	srcPolygon2:	input source of polygon 2 (INPUT_NO, INPUT_FROM_PARAMETER, INPUT_FROM_GDL_STACK)
!	polygon2:		input polygon 2
!	result:			output result (OUTPUT_TO_PARAMETER, OUTPUT_TO_GDL_STACK)
!	GDL stack:		coordX[1], coordY[1], arc[1], ...
!
! Output:
!	polygon1:		output polygon1
!	polygon2:		output polygon2
!	GDL stack:		coordX[1], coordY[1], status[1], ...
! ==============================================================================

dim tempPolygon[][3]

gosub 701
if result = OUTPUT_TO_GDL_STACK then
	if srcPolygon1 = INPUT_FROM_PARAMETER & srcPolygon2 = INPUT_NO then
		for revI=1 to vardim1(polygon1)
			put polygon1[revI][1],
				polygon1[revI][2],
				polygon1[revI][3]
		next revI
	endif
	if srcPolygon1 = INPUT_NO & srcPolygon2 = INPUT_FROM_PARAMETER then
		for revI=1 to vardim1(polygon2)
			put polygon2[revI][1],
				polygon2[revI][2],
				polygon2[revI][3]
		next revI
	endif
	if srcPolygon1 = INPUT_FROM_GDL_STACK | srcPolygon2 = INPUT_FROM_GDL_STACK then
		for revI=1 to vardim1(tempPolygon)
			put tempPolygon[revI][1],
				tempPolygon[revI][2],
				tempPolygon[revI][3]
		next revI
	endif

	end
endif
if srcPolygon1 = INPUT_FROM_PARAMETER & srcPolygon2 = INPUT_NO then end polygon1
if srcPolygon1 = INPUT_NO & srcPolygon2 = INPUT_FROM_PARAMETER then end polygon2
if srcPolygon1 = INPUT_FROM_GDL_STACK | srcPolygon2 = INPUT_FROM_GDL_STACK then end tempPolygon


701:
	if srcPolygon1 = INPUT_FROM_PARAMETER & srcPolygon2 = INPUT_NO then
		tempNumPnts = vardim1(polygon1)

		for revI=1 to int(tempNumPnts / 2)
			tempX = polygon1[revI][1]
			tempY = polygon1[revI][2]
			tempS = polygon1[revI][3]

			polygon1[revI][1] = polygon1[tempNumPnts-revI+1][1]
			polygon1[revI][2] = polygon1[tempNumPnts-revI+1][2]
			polygon1[revI][3] = polygon1[tempNumPnts-revI+1][3]

			polygon1[tempNumPnts-revI+1][1] = tempX
			polygon1[tempNumPnts-revI+1][2] = tempY
			polygon1[tempNumPnts-revI+1][3] = tempS
		next revI

		return
	endif

	if srcPolygon1 = INPUT_NO & srcPolygon2 = INPUT_FROM_PARAMETER then
		tempNumPnts = vardim1(polygon2)

		for revI=1 to int(tempNumPnts / 2)
			tempX = polygon2[revI][1]
			tempY = polygon2[revI][2]
			tempS = polygon2[revI][3]

			polygon2[revI][1] = polygon2[tempNumPnts-revI+1][1]
			polygon2[revI][2] = polygon2[tempNumPnts-revI+1][2]
			polygon2[revI][3] = polygon2[tempNumPnts-revI+1][3]

			polygon2[tempNumPnts-revI+1][1] = tempX
			polygon2[tempNumPnts-revI+1][2] = tempY
			polygon2[tempNumPnts-revI+1][3] = tempS
		next revI

		return
	endif

	if srcPolygon1 = INPUT_FROM_GDL_STACK | srcPolygon2 = INPUT_FROM_GDL_STACK then
		tempNumPnts = nsp/3

		for revI=1 to tempNumPnts
			tempPolygon[revI][1] = get(1)
			tempPolygon[revI][2] = get(1)
			tempPolygon[revI][3] = get(1)
		next revI

		for revI=1 to int(tempNumPnts / 2)
			tempX = tempPolygon[revI][1]
			tempY = tempPolygon[revI][2]
			tempS = tempPolygon[revI][3]

			tempPolygon[revI][1] = tempPolygon[tempNumPnts-revI+1][1]
			tempPolygon[revI][2] = tempPolygon[tempNumPnts-revI+1][2]
			tempPolygon[revI][3] = tempPolygon[tempNumPnts-revI+1][3]

			tempPolygon[tempNumPnts-revI+1][1] = tempX
			tempPolygon[tempNumPnts-revI+1][2] = tempY
			tempPolygon[tempNumPnts-revI+1][3] = tempS
		next revI
	endif
return



PolyOp.png
Frank Beister
Moderator


Thanks. I have the recent versions and have downloaded library development kit, which comes with the library.
bim author since 1994 | bim manager since 2018 | author of selfGDL.de | openGDL | skewed archicad user hall of fame | author of bim-all-doors.gsm
Hmooslechner
Moderator
Next week i have a lot of scripting-Work with this! Many thanks so far!
AC5.5-AC27EduAut, PC-Win10, MacbookAirM1, MacbookM1Max, Win-I7+Nvidia