HTML-Genealogy-Map

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

HTML::Genealogy::Map - Extract and map genealogical events from GEDCOM file

# VERSION

Version 0.03

# DESCRIPTION

This module parses GEDCOM genealogy files and creates an interactive map showing
the locations of births, marriages, and deaths. Events at the same location are
grouped together in a single marker with a scrollable popup.

# SUBROUTINES/METHODS

## onload\_render

Render the map.
It takes two mandatory and one optional parameter.
It returns an array of two elements, the items for the `head` and `body`.

- **gedcom**

README.md  view on Meta::CPAN


    Enable print statements of what's going on

# FEATURES

- Extracts births, marriages, and deaths with location data
- Geocodes locations using multiple fallback providers
- Groups events at the same location (within ~0.1m precision)
- Color-coded event indicators (green=birth, blue=marriage, red=death)
- Sorts events chronologically within each category
- Scrollable popups for locations with more than 5 events
- Persistent caching of geocoding results
- For OpenStreetMap: centers on location with most events

### API SPECIFICATION

#### INPUT

    {
      'gedcom' => { 'type' => 'object', 'can' => 'individuals' },
      'geocoder' => { 'type' => 'object', 'can' => 'geocode' },

ged2map  view on Meta::CPAN

# Generate map based on available API key
if ($google_key) {
	generate_google_map(\%location_groups, $output_file, $google_key);
} else {
	generate_osm_map(\%location_groups, $output_file);
}

print "Map saved to $output_file\n";

# Generate HTML for grouped events
sub generate_popup_html {
	my ($events) = @_;

	my $place = $events->[0]{place};
	my $event_count = scalar(@$events);

	# Add scrollable container if more than 5 events
	my $container_start = '';
	my $container_end = '';
	if ($event_count > 5) {
		$container_start = '<div style="max-height: 300px; overflow-y: auto;">';

ged2map  view on Meta::CPAN

		height => '600px',
		width => '100%',
	);

	# Add markers for each location
	my $first = 1;
	foreach my $loc_key (keys %$location_groups) {
		my $events = $location_groups->{$loc_key};
		my ($lat, $lon) = split /,/, $loc_key;

		my $html = generate_popup_html($events);

		$map->add_marker(
			point => [$lat, $lon],
			html => $html,
		);

		# Center on first location
		if ($first) {
			$map->center([$lat, $lon]);
			$map->zoom(4);

ged2map  view on Meta::CPAN

	my ($location_groups, $file) = @_;

	# Create HTML::OSM object
	my $osm = HTML::OSM->new(zoom => 12);

	# Add markers for each location
	foreach my $loc_key (keys %$location_groups) {
		my $events = $location_groups->{$loc_key};
		my ($lat, $lon) = split /,/, $loc_key;

		my $html = generate_popup_html($events);

		$osm->add_marker(
			point => [$lat, $lon],
			html => $html,
		);
	}

	# Find location with most events
	my ($center_lat, $center_lon) = (0, 0);
	my $max_events = 0;

lib/HTML/Genealogy/Map.pm  view on Meta::CPAN

Version 0.04

=cut

our $VERSION = '0.04';

=head1 DESCRIPTION

This module parses GEDCOM genealogy files and creates an interactive map showing
the locations of births, marriages, and deaths. Events at the same location are
grouped together in a single marker with a scrollable popup.

=head1 SUBROUTINES/METHODS

=head2 onload_render

Render the map.
It takes two mandatory and one optional parameter.
It returns an array of two elements, the items for the C<head> and C<body>.

=over 4

lib/HTML/Genealogy/Map.pm  view on Meta::CPAN

=item * Extracts births, marriages, and deaths with location data

=item * Geocodes locations using multiple fallback providers

=item * Groups events at the same location (within ~0.1m precision)

=item * Color-coded event indicators (green=birth, blue=marriage, red=death)

=item * Sorts events chronologically within each category

=item * Scrollable popups for locations with more than 5 events

=item * Persistent caching of geocoding results

=item * For OpenStreetMap: centers on location with most events

=back

=head3	API SPECIFICATION

=head4	INPUT

lib/HTML/Genealogy/Map.pm  view on Meta::CPAN

	if ($google_key) {
		$map = _generate_google_map(\%location_groups, $height, $width, $google_key);
	} else {
		$map = _generate_osm_map(\%location_groups, $height, $width);
	}

	return $map->onload_render();
}

# Generate HTML for grouped events
sub _generate_popup_html {
	my ($events) = @_;

	my $place = $events->[0]{place};
	my $event_count = scalar(@$events);

	# Add scrollable container if more than 5 events
	my $container_start = '';
	my $container_end = '';
	if ($event_count > 5) {
		$container_start = '<div style="max-height: 300px; overflow-y: auto;">';

lib/HTML/Genealogy/Map.pm  view on Meta::CPAN

		height => $height,
		width => $width
	);

	# Add markers for each location
	my $first = 1;
	foreach my $loc_key (keys %$location_groups) {
		my $events = $location_groups->{$loc_key};
		my ($lat, $lon) = split /,/, $loc_key;

		my $html = _generate_popup_html($events);

		$map->add_marker(
			point => [$lat, $lon],
			html => $html,
		);

		# Center on first location
		if ($first) {
			$map->center([$lat, $lon]);
			$map->zoom(4);

lib/HTML/Genealogy/Map.pm  view on Meta::CPAN

	my ($location_groups, $height, $width) = @_;

	# Create HTML::OSM object
	my $osm = HTML::OSM->new(zoom => 12, height => $height, width => $width);

	# Add markers for each location
	foreach my $loc_key (keys %$location_groups) {
		my $events = $location_groups->{$loc_key};
		my ($lat, $lon) = split /,/, $loc_key;

		my $html = _generate_popup_html($events);

		$osm->add_marker(
			point => [$lat, $lon],
			html => $html,
		);
	}

	# Find location with most events
	my ($center_lat, $center_lon) = (0, 0);
	my $max_events = 0;



( run in 1.559 second using v1.01-cache-2.11-cpan-364913b4093 )