Jump to content

File:Divisibility lattice.svg

Page contents not supported in other languages.
This is a file from the Wikimedia Commons
From Wikipedia, the free encyclopedia
Original file (SVG file, nominally 462 × 475 pixels, file size: 37 KB)

Summary

Description A lattice of the non-negative integers partially ordered by divisibility; each number is connected to its divisors in the row below. Re-working of File:Infinite lattice of divisors.svg
Date
Source Own work
Author Mathnerd314159
Permission
(Reusing this file)
Public domain I, the copyright holder of this work, release this work into the public domain. This applies worldwide.
In some countries this may not be legally possible; if so:
I grant anyone the right to use this work for any purpose, without any conditions, unless such conditions are required by law.
SVG development
InfoField
 The SVG code is valid.
 This vector image was created with Python.
Source code
InfoField

Python code

import math

def create_lattice_svg():
    # --- Configuration ---
    # SVG dimensions.
    row_height = 95
    node_spacing = 77
    node_radius = 20
    
    # --- Lattice Data ---
    # Define the numbers for each row of the lattice based on number of prime factors.
    # The key (0-4) serves as both the number of factors and the row identifier.
    lattice_data = {
        4: [0],              # The top node (0)
        3: [8, 12, 18, 20, 27],  # Numbers with three prime factors
        2: [4, 6, 9, 10, 14], # Numbers with two prime factors
        1: [2, 3, 5, 7],     # Prime numbers
        0: [1]               # The number 1 (zero factors)
    }

    # --- Create a list of node objects with positions ---
    nodes = []
    
    # Determine the widest row to calculate total SVG width.
    max_nodes_per_row = 0
    for row in lattice_data.values():
        if len(row) > max_nodes_per_row:
            max_nodes_per_row = len(row)
    
    # Adjust for ellipsis node
    max_nodes_per_row += 1 

    # Calculate total SVG dimensions with padding.
    width = max_nodes_per_row * node_spacing
    num_rows = len(lattice_data)
    height = num_rows * row_height
    
    # Build the nodes list and calculate their positions.
    row_keys = sorted(lattice_data.keys(), reverse=True)
    for i, num_factors in enumerate(row_keys):
        numbers = sorted(lattice_data[num_factors])
        # Ellipses are added to rows that aren't the top or bottom
        has_ellipsis = num_factors not in [0, 4]
        
        # Calculate the y-position for the current row, from the top down.
        y_pos = row_height * i + row_height / 2
        
        # Calculate x-positions to center the numbers in the row.
        num_nodes_in_row = len(numbers) + (1 if has_ellipsis else 0)
        half_width = width / 2
        half_node_span = ((num_nodes_in_row -1) / 2) * node_spacing
        start_x = half_width - half_node_span
        
        for j, number in enumerate(numbers):
            x_pos = start_x + j * node_spacing
            node = {
                'value': number,
                'type': 'number',
                'num_factors': num_factors,
                'x_pos': x_pos,
                'y_pos': y_pos
            }
            nodes.append(node)
        
        # Add positions for ellipsis nodes.
        if has_ellipsis:
            ellipsis_x_pos = start_x + len(numbers) * node_spacing
            ellipsis_y_pos = y_pos
            ellipsis_node = {
                'value': '···',
                'type': 'ellipsis',
                'num_factors': num_factors,
                'x_pos': ellipsis_x_pos,
                'y_pos': ellipsis_y_pos
            }
            nodes.append(ellipsis_node)

    # --- Start the SVG string with the header and styles ---
    svg_string = f'''<svg width="{width}" height="{height}" xmlns="http://www.w3.org/2000/svg">
    <defs>
        <style type="text/css">
        .solid-line {{ 
            fill: none;
            stroke: #000000;
            stroke-width: 1.5;
            stroke-linecap: butt;
            stroke-linejoin: miter;
            stroke-miterlimit: 4;
            stroke-opacity: 1;
            stroke-dasharray: none;
            stroke-dashoffset: 0;
        }}
        .dotted-line {{ 
            fill: none;
            stroke: #000000;
            stroke-width: 1.5;
            stroke-linecap: butt;
            stroke-linejoin: miter;
            stroke-miterlimit: 4;
            stroke-opacity: 1;
            stroke-dasharray: 1.5, 4.5;
            stroke-dashoffset: 0;
        }}
        .node-circle {{ 
            fill: #ffffff;
            fill-opacity: 1;
            fill-rule: evenodd;
            stroke: none;
        }}
        .node-text {{ 
            font-size: 30px;
            font-style: normal;
            font-variant: normal;
            font-weight: normal;
            font-stretch: normal;
            text-indent: 0;
            text-align: start;
            text-decoration: none;
            line-height: normal;
            letter-spacing: normal;
            word-spacing: normal;
            text-transform: none;
            direction: ltr;
            block-progression: tb;
            writing-mode: lr-tb;
            text-anchor: middle;
            dominant-baseline: middle;
            color: #000000;
            fill: #000000;
            fill-opacity: 1;
            fill-rule: nonzero;
            stroke: none;
            stroke-width: 1px;
            marker: none;
            visibility: visible;
            display: inline;
            overflow: visible;
            enable-background: accumulate;
            font-family: Liberation Serif, Times New Roman, serif;
        }}
        </style>
    </defs>'''
    
    # Painting order: lines first, then circles, then text on top. This is the order in which we add elements to the SVG string.
    
    # --- Step 1: Draw all Lattice Lines ---
    for parent_node in nodes:
        for child_node in nodes:
            # Skip if they are the same node
            if parent_node == child_node:
                continue
            # Only connect nodes that are one level apart in terms of prime factors
            if parent_node['num_factors'] != child_node['num_factors'] + 1:
                continue

            x1, y1 = parent_node['x_pos'], parent_node['y_pos']
            x2, y2 = child_node['x_pos'], child_node['y_pos']

            line_class = None
            
            # Solid lines between numbers based on divisibility
            if (parent_node['type'] == 'number' and child_node['type'] == 'number' and
                parent_node['value'] % child_node['value'] == 0):
                line_class = "solid-line"

            # Dotted lines from numbers/ellipsis in the row below to the ellipsis
            if (parent_node['type'] == 'ellipsis'):
                line_class = "dotted-line"
                
            # Dotted lines from 0 to the top row
            if (parent_node['value'] == 0 and child_node['num_factors'] == 3):
                line_class = "dotted-line"

            # If a condition is met, draw the line
            if line_class:
                # Adjust start and end points of lines to meet the circle edges.
                dy = y2 - y1
                dx = x2 - x1
                angle = math.atan2(dy, dx)
                
                x1_adj = x1 + node_radius * math.cos(angle)
                y1_adj = y1 + node_radius * math.sin(angle)
                x2_adj = x2 - node_radius * math.cos(angle)
                y2_adj = y2 - node_radius * math.sin(angle)
                
                svg_string += f'''
    <line x1="{x1_adj}" y1="{y1_adj}" x2="{x2_adj}" y2="{y2_adj}" class="{line_class}" />'''

    # --- Step 2: Draw all Lattice Nodes ---
    # actually, it looks better without the circles, they just cut off the lines
    #for node in nodes:
    #    svg_string += f'''
    #<circle cx="{node['x_pos']}" cy="{node['y_pos']}" r="{node_radius}" class="node-circle" />'''

    # --- Step 3: Draw all Lattice Node Text ---        
    for node in nodes:
        text_content = node['value']
        svg_string += f'''
    <text x="{node['x_pos']}" y="{node['y_pos']}" dy="0.1em" class="node-text">{text_content}</text>'''
    
    # --- Close the SVG tag ---
    svg_string += "\n</svg>"
    
    return svg_string


if __name__ == "__main__":
    svg_code = create_lattice_svg()
    
    # Write the SVG string to a file
    file_path = "divisibility_lattice.svg"
    with open(file_path, "w") as f:
        f.write(svg_code)
    
    print(f"SVG file generated successfully at: {file_path}")

Licensing

I, the copyright holder of this work, hereby publish it under the following license:
Creative Commons CC-Zero This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Dedication.
The person who associated a work with this deed has dedicated the work to the public domain by waiving all of their rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.

Captions

Add a one-line explanation of what this file represents

Items portrayed in this file

depicts

File history

Click on a date/time to view the file as it appeared at that time.

Date/TimeThumbnailDimensionsUserComment
current10:05, 29 September 2025Thumbnail for version as of 10:05, 29 September 2025462 × 475 (37 KB)Watchducksmall layout changes to improve readability
17:53, 19 September 2025Thumbnail for version as of 17:53, 19 September 2025462 × 475 (8 KB)Mathnerd314159fix height
17:40, 19 September 2025Thumbnail for version as of 17:40, 19 September 2025462 × 523 (8 KB)Mathnerd314159{{Information |Description=A lattice of the non-negative integers partially ordered by divisibility; each number is connected to its divisors in the row below. Re-working of File:Infinite lattice of divisors.svg |Source={{own}} |Date=2025 |Author= Mathnerd314159 |Permission={{PD-self}} |other_versions= |other fields={{File generation description|SVG tool=Python|Syntax=python|Code= import math def create_lattice_svg(): # --- Configuration --- # SVG dimensi...

The following 2 pages use this file:

Metadata