use Algorithm::Loops qw/ NestedLoops /; $|++; $i = 0; $toggle = -1; @p = qw|ROI1 ROI2 ROI3 ROI4 ROI5 ROI6 ROI7|; $precision = shift; $match = shift; $minpoints = shift; system('cls'); if ((!$precision) || (!$match) || (!$minpoints)) { print "Usage: pointfilter.exe x y z\n\n\tx,\tPrecision in pixels for the distances.", "\n\t\tDecrease this value to lower total points.", "\n\t\tBe aware, lowering it too much will return bad solutions.", "\n\t\tTypical values are 10 - 20.", "\n\n\ty,\tNumber of distances that a point must be within toelerence to be considered valid.", "\n\t\tThis number will typically be 4 or 5, 6 is maximum.", "\n\n\tz,\tThe minimum amount of points contained in the best fit.", "\n\t\tTypical values would be 4 or 5, minimum is 4, maximum is 7."; exit (0); } ##### Get Template Distances ##### open (TEMPLATE, "; close (TEMPLATE); for $j(0..6) { for $k(0..6) { if ($j == $k) {} else { chomp $avedist[$i]; $data->{template}->{$p[$j]}->{$p[$k]}->{AVE} = $avedist[$i]; $i++; } } } ##### Get the Film Point Data ##### $i = 0; $alpha = "A"; $m = 0; open (POINTS, ") { chomp $_; ($a,$b,$c) = split(/\t/,$_); if ($a == 1) { $toggle *= -1; if ($toggle < 0) { $i++; $alpha = "A"; $toggle = 1; } } if ($b == -1) { $i++; $alpha = "A"; $toggle = -1; } else { $data->{$p[$i]}->{$p[$i]."point".$alpha}->{X} = $b; $data->{$p[$i]}->{$p[$i]."point".$alpha++}->{Y} = $c; $m++; } } close(POINTS); print "Total number of Points = $m\n\n"; print "Running first filtering pass..."; ##### First Pass at Filtering the Data ##### $passed = 0; for $i(0..6) { foreach $testpoints (sort keys %{$data->{$p[$i]}}) { $j = 0; $testX = $data->{$p[$i]}->{$testpoints}->{X}; $testY = $data->{$p[$i]}->{$testpoints}->{Y}; for $l(0..6) { if ($l == $i) {} else { $truedist = $data->{template}->{$p[$i]}->{$p[$l]}->{AVE}; foreach $points(sort keys %{$data->{$p[$l]}}) { $X = $data->{$p[$l]}->{$points}->{X}; $Y = $data->{$p[$l]}->{$points}->{Y}; $distance = sqrt(($testX - $X)**2 + ($testY - $Y)**2); $data->{$p[$i]}->{$testpoints}->{$p[$l]}->{$points} = abs($truedist - $distance); if (abs($truedist - $distance) < $precision) { $passed = 1; } } if ($passed == 1) { $j++; $passed = 0; } } } if ($j < $match) { delete $data->{$p[$i]}->{$testpoints}; } } } $i = 0; foreach (@p) { foreach $key(sort keys %{$data->{$_}}){ $i++; } } print "done!\n", $m - $i ," points were filtered. $i points remaining.\n\n"; print "Calculating the total number of combinations...."; ##### Calculate the Combinations ##### @arrays = ([keys %{$data->{ROI1}}], [keys %{$data->{ROI2}}], [keys %{$data->{ROI3}}], [keys %{$data->{ROI4}}], [keys %{$data->{ROI5}}], [keys %{$data->{ROI6}}], [keys %{$data->{ROI7}}]); NestedLoops( [ map [ undef, @$_ ], @arrays ], sub { $count = 0; $string = join '', grep { defined && ++$count } @_; push @combinations, [grep { defined && ++$count } @_] if $count >= $minpoints; }, ); print "done!\nThere are $#combinations total combinations\n\n"; print "Running final filter..."; ##### Final Filter ##### $lowscore = 1000000; foreach (@combinations){ @fit = @$_; $i = 0; for $j(0..$#fit) { ($region1,$trash) = split (/point/,$fit[$j]); for $k($j+1..$#fit) { ($region2,$trash) = split (/point/,$fit[$k]); $i++; $tempsum += $data->{$region1}->{$fit[$j]}->{$region2}->{$fit[$k]}; if ($data->{$region1}->{$fit[$j]}->{$region2}->{$fit[$k]} > ($precision * 1.25)) { $failed = 1; } } } do { @bestfit = @fit; $lowscore = $tempsum / $i; } unless (($lowscore < ($tempsum / $i)) || ($lowscore == 0) || ($failed == 1)); undef $tempsum; $failed = 0; } print "done!\n\n\n"; print "Bestfit = \n"; foreach $bf(@bestfit) { ($region,$trash) = split (/point/,$bf); print "$data->{$region}->{$bf}->{X} | $data->{$region}->{$bf}->{Y}\t"; } print "\n";