|
@@ -1,5 +1,6 @@
|
|
|
import pygame
|
|
import pygame
|
|
|
import math
|
|
import math
|
|
|
|
|
+import os
|
|
|
from pygame.locals import *
|
|
from pygame.locals import *
|
|
|
from OpenGL.GL import *
|
|
from OpenGL.GL import *
|
|
|
from OpenGL.GLU import *
|
|
from OpenGL.GLU import *
|
|
@@ -32,10 +33,45 @@ def setup_opengl(width, height):
|
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, (0.8, 0.8, 0.8, 1))
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, (0.8, 0.8, 0.8, 1))
|
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, (1, 1, 1, 1))
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, (1, 1, 1, 1))
|
|
|
|
|
|
|
|
-def draw_sphere(radius, color, slices=30, stacks=30):
|
|
|
|
|
|
|
+def generate_fibonacci_points_on_sphere(n, radius):
|
|
|
|
|
+ """
|
|
|
|
|
+ Generate n uniformly distributed points on a sphere using Fibonacci sphere algorithm
|
|
|
|
|
+ """
|
|
|
|
|
+ points = []
|
|
|
|
|
+ phi = math.pi * (3. - math.sqrt(5.)) # Golden angle in radians
|
|
|
|
|
+
|
|
|
|
|
+ for i in range(n):
|
|
|
|
|
+ y = 1 - (i / float(n - 1)) * 2 # y goes from 1 to -1
|
|
|
|
|
+ radius_at_y = math.sqrt(1 - y*y) # Radius at y
|
|
|
|
|
+
|
|
|
|
|
+ theta = phi * i # Golden angle increment
|
|
|
|
|
+
|
|
|
|
|
+ x = math.cos(theta) * radius_at_y
|
|
|
|
|
+ z = math.sin(theta) * radius_at_y
|
|
|
|
|
+
|
|
|
|
|
+ # Scale to the desired radius
|
|
|
|
|
+ points.append((x * radius, y * radius, z * radius))
|
|
|
|
|
+
|
|
|
|
|
+ return points
|
|
|
|
|
+
|
|
|
|
|
+def draw_sphere(radius, color, slices=30, stacks=30, draw_points=False):
|
|
|
"""
|
|
"""
|
|
|
Draw a sphere with specified radius
|
|
Draw a sphere with specified radius
|
|
|
radius: radius of the sphere
|
|
radius: radius of the sphere
|
|
|
|
|
+ draw_points: whether to draw 88 red points on the sphere surface
|
|
|
|
|
+ """
|
|
|
|
|
+ # Call the new function with 88 points if draw_points is True
|
|
|
|
|
+ if draw_points:
|
|
|
|
|
+ draw_sphere_with_n_points(radius, color, 88)
|
|
|
|
|
+ else:
|
|
|
|
|
+ draw_sphere_with_n_points(radius, color, 0)
|
|
|
|
|
+
|
|
|
|
|
+def draw_sphere_with_n_points(radius, color, num_points, slices=30, stacks=30):
|
|
|
|
|
+ """
|
|
|
|
|
+ Draw a sphere with specified radius and a specific number of red points
|
|
|
|
|
+ radius: radius of the sphere
|
|
|
|
|
+ color: color of the sphere
|
|
|
|
|
+ num_points: number of red points to draw on the sphere surface
|
|
|
"""
|
|
"""
|
|
|
glPushMatrix()
|
|
glPushMatrix()
|
|
|
|
|
|
|
@@ -85,19 +121,162 @@ def draw_sphere(radius, color, slices=30, stacks=30):
|
|
|
glVertex3f(x * zr0, y * zr0, z0)
|
|
glVertex3f(x * zr0, y * zr0, z0)
|
|
|
glEnd()
|
|
glEnd()
|
|
|
|
|
|
|
|
|
|
+ # Draw red points on the sphere surface if requested
|
|
|
|
|
+ if num_points > 0:
|
|
|
|
|
+ # Generate specified number of uniformly distributed points on the sphere
|
|
|
|
|
+ points = generate_fibonacci_points_on_sphere(num_points, radius)
|
|
|
|
|
+
|
|
|
|
|
+ # Save current material properties and disable lighting for points
|
|
|
|
|
+ glDisable(GL_LIGHTING)
|
|
|
|
|
+
|
|
|
|
|
+ # Set color to red for points
|
|
|
|
|
+ glColor3f(1.0, 0.0, 0.0) # Red color
|
|
|
|
|
+
|
|
|
|
|
+ # Draw points
|
|
|
|
|
+ glPointSize(5.0) # Size of the points
|
|
|
|
|
+ glBegin(GL_POINTS)
|
|
|
|
|
+ for point in points:
|
|
|
|
|
+ glVertex3f(point[0], point[1], point[2])
|
|
|
|
|
+ glEnd()
|
|
|
|
|
+
|
|
|
|
|
+ # Re-enable lighting
|
|
|
|
|
+ glEnable(GL_LIGHTING)
|
|
|
|
|
+
|
|
|
glPopMatrix()
|
|
glPopMatrix()
|
|
|
|
|
|
|
|
|
|
|
|
|
-def draw_concentric_spheres():
|
|
|
|
|
- """Draw three concentric spheres (big sphere containing smaller spheres)"""
|
|
|
|
|
- # First sphere (smallest, innermost) - Red (drawn first so it's not obscured)
|
|
|
|
|
- draw_sphere(1.0, (1.0, 0.0, 0.0, 0.4)) # Red with semi-transparency
|
|
|
|
|
|
|
+# Define directories to exclude from the analysis
|
|
|
|
|
+EXCLUDED_DIRS = {
|
|
|
|
|
+ 'node_modules', '.vscode', '.git', '__pycache__', '.pytest_cache',
|
|
|
|
|
+ '.venv', 'venv', 'env', '.env', 'dist', 'build', '.next', '.nuxt',
|
|
|
|
|
+ 'target', 'tmp', 'temp', '.idea', '.DS_Store', 'Thumbs.db'
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+def analyze_directory_structure(root_path, max_depth=10):
|
|
|
|
|
+ """
|
|
|
|
|
+ Analyze the directory tree and return the depth and folder counts per level
|
|
|
|
|
+ Returns a tuple: (max_depth, list of counts per level)
|
|
|
|
|
+ """
|
|
|
|
|
+ if not os.path.exists(root_path):
|
|
|
|
|
+ print(f"Directory does not exist: {root_path}")
|
|
|
|
|
+ return 1, [0] # Return 1 level with 0 items if directory doesn't exist
|
|
|
|
|
+
|
|
|
|
|
+ # Initialize a list to hold the count of folders at each level
|
|
|
|
|
+ level_counts = []
|
|
|
|
|
+
|
|
|
|
|
+ def traverse_directory(path, current_depth=0):
|
|
|
|
|
+ if current_depth >= max_depth:
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ # Ensure the level_counts list has enough elements
|
|
|
|
|
+ if len(level_counts) <= current_depth:
|
|
|
|
|
+ level_counts.extend([0] * (current_depth + 1 - len(level_counts)))
|
|
|
|
|
+
|
|
|
|
|
+ try:
|
|
|
|
|
+ # Count only directories in the current directory
|
|
|
|
|
+ items = os.listdir(path)
|
|
|
|
|
+
|
|
|
|
|
+ # Filter out excluded directories
|
|
|
|
|
+ filtered_items = [item for item in items if item not in EXCLUDED_DIRS]
|
|
|
|
|
+
|
|
|
|
|
+ # Count only directories (not files)
|
|
|
|
|
+ dir_count = 0
|
|
|
|
|
+ for item in filtered_items:
|
|
|
|
|
+ item_path = os.path.join(path, item)
|
|
|
|
|
+ if os.path.isdir(item_path):
|
|
|
|
|
+ dir_count += 1
|
|
|
|
|
+
|
|
|
|
|
+ level_counts[current_depth] += dir_count
|
|
|
|
|
+
|
|
|
|
|
+ # Recursively traverse subdirectories
|
|
|
|
|
+ for item in filtered_items:
|
|
|
|
|
+ item_path = os.path.join(path, item)
|
|
|
|
|
+ if os.path.isdir(item_path):
|
|
|
|
|
+ traverse_directory(item_path, current_depth + 1)
|
|
|
|
|
+ except PermissionError:
|
|
|
|
|
+ # Skip directories that can't be accessed
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ traverse_directory(root_path)
|
|
|
|
|
+
|
|
|
|
|
+ # Return the max depth and the counts per level
|
|
|
|
|
+ max_depth_found = len(level_counts) - 1 if level_counts else 0
|
|
|
|
|
+ return max_depth_found + 1, level_counts
|
|
|
|
|
+
|
|
|
|
|
+def draw_concentric_spheres_from_directory():
|
|
|
|
|
+ """Draw concentric spheres based on directory tree levels"""
|
|
|
|
|
+ root_path = "E:\\agricultural_research_platform"
|
|
|
|
|
+ num_levels = analyze_directory_levels(root_path)
|
|
|
|
|
+
|
|
|
|
|
+ # Limit the number of spheres to prevent performance issues
|
|
|
|
|
+ max_spheres = 5 # Maximum number of spheres to display
|
|
|
|
|
+ num_levels = min(num_levels, max_spheres)
|
|
|
|
|
+
|
|
|
|
|
+ # Ensure we have at least 1 level
|
|
|
|
|
+ num_levels = max(1, num_levels)
|
|
|
|
|
+
|
|
|
|
|
+ print(f"Directory has {num_levels} levels (limited to {max_spheres} spheres for performance)")
|
|
|
|
|
+
|
|
|
|
|
+ # Draw spheres for each level - from smallest to largest
|
|
|
|
|
+ for i in range(num_levels):
|
|
|
|
|
+ # Calculate radius based on level (starting from 1.0)
|
|
|
|
|
+ radius = (i + 1) * 1.0
|
|
|
|
|
+ # White color with 90% transparency
|
|
|
|
|
+ draw_sphere(radius, (1.0, 1.0, 1.0, 0.1), draw_points=True) # White with 90% transparency and points
|
|
|
|
|
+
|
|
|
|
|
+# Global variables to store the directory analysis results (analyze once at startup)
|
|
|
|
|
+NUM_LEVELS = None
|
|
|
|
|
+LEVEL_COUNTS = None
|
|
|
|
|
+
|
|
|
|
|
+def get_directory_info():
|
|
|
|
|
+ global NUM_LEVELS, LEVEL_COUNTS
|
|
|
|
|
+ if NUM_LEVELS is None or LEVEL_COUNTS is None:
|
|
|
|
|
+ root_path = "E:\\agricultural_research_platform"
|
|
|
|
|
+ raw_levels, raw_counts = analyze_directory_structure(root_path)
|
|
|
|
|
+
|
|
|
|
|
+ # Limit the number of spheres to prevent performance issues
|
|
|
|
|
+ max_spheres = 5 # Maximum number of spheres to display
|
|
|
|
|
+ NUM_LEVELS = min(raw_levels, max_spheres)
|
|
|
|
|
+
|
|
|
|
|
+ # Ensure we have at least 1 level
|
|
|
|
|
+ NUM_LEVELS = max(1, NUM_LEVELS)
|
|
|
|
|
+
|
|
|
|
|
+ # Take only the counts for the levels we'll display
|
|
|
|
|
+ LEVEL_COUNTS = raw_counts[:NUM_LEVELS]
|
|
|
|
|
+
|
|
|
|
|
+ print(f"Directory has {raw_levels} levels (limited to {NUM_LEVELS} spheres for performance)")
|
|
|
|
|
+ print(f"Items per level: {LEVEL_COUNTS}")
|
|
|
|
|
+
|
|
|
|
|
+ return NUM_LEVELS, LEVEL_COUNTS
|
|
|
|
|
+
|
|
|
|
|
+def draw_concentric_spheres_from_directory():
|
|
|
|
|
+ """Draw concentric spheres based on directory tree levels"""
|
|
|
|
|
+ num_levels, level_counts = get_directory_info()
|
|
|
|
|
+
|
|
|
|
|
+ # Draw a large red point at the origin to represent the root node
|
|
|
|
|
+ draw_root_node()
|
|
|
|
|
+
|
|
|
|
|
+ # Draw spheres for each level - from smallest to largest
|
|
|
|
|
+ for i in range(num_levels):
|
|
|
|
|
+ # Calculate radius based on level (starting from 1.0)
|
|
|
|
|
+ radius = (i + 1) * 1.0
|
|
|
|
|
+ # Number of points based on the count of files/folders at this level
|
|
|
|
|
+ num_points = level_counts[i] if i < len(level_counts) else 0
|
|
|
|
|
+ # White color with 90% transparency
|
|
|
|
|
+ draw_sphere_with_n_points(radius, (1.0, 1.0, 1.0, 0.1), num_points) # White with 90% transparency and dynamic points
|
|
|
|
|
+
|
|
|
|
|
+def draw_root_node():
|
|
|
|
|
+ """Draw a large red point at the center to represent the root node"""
|
|
|
|
|
+ glDisable(GL_LIGHTING) # Disable lighting to ensure pure red color
|
|
|
|
|
+ glColor3f(1.0, 0.0, 0.0) # Red color
|
|
|
|
|
|
|
|
- # Second sphere (medium) - Green
|
|
|
|
|
- draw_sphere(2.0, (0.0, 1.0, 0.0, 0.3)) # Green with semi-transparency
|
|
|
|
|
|
|
+ # Draw a large point at the origin (center of all spheres)
|
|
|
|
|
+ glPointSize(10.0) # Larger point size for the root node
|
|
|
|
|
+ glBegin(GL_POINTS)
|
|
|
|
|
+ glVertex3f(0.0, 0.0, 0.0) # At the center/origin
|
|
|
|
|
+ glEnd()
|
|
|
|
|
|
|
|
- # Third sphere (largest, outermost) - Blue
|
|
|
|
|
- draw_sphere(3.0, (0.0, 0.0, 1.0, 0.2)) # Blue with higher transparency
|
|
|
|
|
|
|
+ glEnable(GL_LIGHTING) # Re-enable lighting
|
|
|
|
|
|
|
|
def main():
|
|
def main():
|
|
|
display, width, height = init_pygame()
|
|
display, width, height = init_pygame()
|
|
@@ -149,8 +328,8 @@ def main():
|
|
|
if auto_rotate:
|
|
if auto_rotate:
|
|
|
glRotatef(pygame.time.get_ticks() * 0.01, 0, 1, 0)
|
|
glRotatef(pygame.time.get_ticks() * 0.01, 0, 1, 0)
|
|
|
|
|
|
|
|
- # Draw the concentric spheres
|
|
|
|
|
- draw_concentric_spheres()
|
|
|
|
|
|
|
+ # Draw the concentric spheres based on directory levels
|
|
|
|
|
+ draw_concentric_spheres_from_directory()
|
|
|
|
|
|
|
|
pygame.display.flip()
|
|
pygame.display.flip()
|
|
|
clock.tick(60)
|
|
clock.tick(60)
|