Vector2FunctionClip
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RicardoSantos

//@version=5

// @description Sutherland-Hodgman polygon clipping algorithm.
// reference:
// .
//			https://rosettacode.org/wiki/Sutherland-Hodgman_polygon_clipping
// .
library('Vector2FunctionClip')



//#region	-> Imports and helper functions:

import RicardoSantos/CommonTypesMath/1 as TMath
import RicardoSantos/Vector2/1 as Vector2
import RicardoSantos/Vector2Array/1 as Vector2a
import RicardoSantos/Segment2/1 as Segment2
import RicardoSantos/Vector2DrawLine/1 as line

inside (TMath.Vector2 p, TMath.Vector2 cp1, TMath.Vector2 cp2) =>
	(cp2.x - cp1.x) * (p.y - cp1.y) > (cp2.y - cp1.y) * (p.x - cp1.x)

//#endregion

// clip () {

// @function Perform Clip operation on a vector with another.
// @param source    array<Vector2> . Source polygon to be clipped.
// @param reference array<Vector2> . Reference polygon to clip source.
// @returns array<Vector2>.
export method clip (array<TMath.Vector2> source, array<TMath.Vector2> reference) =>
	int _size_ref = array.size(source)
	_outputList = array.copy(source)
	_cp1 = array.get(reference, array.size(reference)-1)
	for _cp2 in reference
		_input_list = _outputList
		_outputList := array.new<TMath.Vector2>(0)
		_s = array.get(_input_list, array.size(_input_list)-1)
		for [_i, _e] in _input_list
			if inside(_e, _cp1, _cp2)
				if not inside(_s, _cp1, _cp2)
					array.push(_outputList, Segment2.intersection(Segment2.new(_cp1, _cp2), Segment2.new(_s, _e)))
				array.push(_outputList, _e)
			else if inside(_s, _cp1, _cp2)
				array.push(_outputList, Segment2.intersection(Segment2.new(_cp1, _cp2), Segment2.new(_s, _e)))
			_s := _e
		_cp1 := _cp2
	_outputList

// TEST: 20230221 RS
array<TMath.Vector2> source    = Vector2a.from(input.string('50,150 ; 200,50 ; 350,150 ; 350,300 ; 250,300 ; 200,250 ; 150,350 ; 100,250 ; 100,200'))
array<TMath.Vector2> reference = Vector2a.from(input.string('100,100 ; 300,100 ; 300,300 ; 100,300'))
for [_i, _e] in source
	_e.x += bar_index
	source.set(_i, _e)
for [_i, _e] in reference
	_e.x += bar_index
	source.set(_i, _e)
if barstate.islast
	TMath.Vector2 _previous = source.last()
	for [_i, _e] in source
		line.new(_previous, _e, color=#a0a0a0) , _previous := _e
	_previous := reference.last()
	for [_i, _e] in reference
		line.new(_previous, _e, color=#cc4545) , _previous := _e
	
	array<TMath.Vector2> _clipped = clip(source, reference)
	_previous := _clipped.last()
	for [_i, _e] in _clipped
		line.new(_previous, _e, color=#69cc45,style='dsh') , _previous := _e

// }
