Math-Polygon

 view release on metacpan or  search on metacpan

lib/Math/Polygon/Clip.pm  view on Meta::CPAN

# This code is part of Perl distribution Math-Polygon version 2.00.
# The POD got stripped from this file by OODoc version 3.03.
# For contributors see file ChangeLog.

# This software is copyright (c) 2004-2025 by Mark Overmeer.

# This is free software; you can redistribute it and/or modify it under
# the same terms as the Perl 5 programming language system itself.
# SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later

#oodist: *** DO NOT USE THIS VERSION FOR PRODUCTION ***
#oodist: This file contains OODoc-style documentation which will get stripped
#oodist: during its release in the distribution.  You can use this file for
#oodist: testing, however the code of this development version may be broken!

package Math::Polygon::Clip;{
our $VERSION = '2.00';
}

use parent 'Exporter';

use strict;
use warnings;

our @EXPORT = qw/
	polygon_line_clip
	polygon_fill_clip1
/;

use Log::Report  'math-polygon';
use List::Util    qw/min max/;

use Math::Polygon::Calc;

sub _inside($$);
sub _cross($$$);
sub _cross_inside($$$);
sub _cross_x($$$);
sub _cross_y($$$);
sub _remove_doubles(@);

#--------------------

sub polygon_fill_clip1($@)
{	my $bbox = shift;
	my ($xmin, $ymin, $xmax, $ymax) = @$bbox;
	@_ or return ();  # empty list of points

	# Collect all crosspoints with axes, plus the original points
	my $next   = shift;
	my @poly   = $next;
	while(@_)
	{	$next  = shift;
		push @poly, _cross($bbox, $poly[-1], $next), $next;
	}

	# crop them to the borders: outside is projected on the sides
	my @cropped;
	foreach (@poly)
	{	my ($x,$y) = @$_;
		$x = $xmin if $x < $xmin;
		$x = $xmax if $x > $xmax;
		$y = $ymin if $y < $ymin;
		$y = $ymax if $y > $ymax;
		push @cropped, [$x, $y];
	}

	polygon_beautify +{despike => 1}, @cropped;
}


sub polygon_line_clip($@)
{	my $bbox = shift;
	my ($xmin, $ymin, $xmax, $ymax) = @$bbox;

	my @frags;
	my $from   = shift;
	my $fromin = _inside $bbox, $from;
	push @frags, [ $from ] if $fromin;

	while(@_)
	{	my $next   = shift;
		my $nextin = _inside $bbox, $next;

		if($fromin && $nextin)       # stay within
		{	push @{$frags[-1]}, $next;
		}
		elsif($fromin && !$nextin)   # leaving
		{	push @{$frags[-1]}, _cross_inside $bbox, $from, $next;
		}
		elsif($nextin)               # entering
		{	my @cross = _cross_inside $bbox, $from, $next;
			push @frags, [ @cross, $next ];



( run in 0.824 second using v1.01-cache-2.11-cpan-39bf76dae61 )