122 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package app
 | 
						|
 | 
						|
import (
 | 
						|
	"sync"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	ChunkSize = 16
 | 
						|
)
 | 
						|
 | 
						|
// Point represents the request body for setting cell position
 | 
						|
type Point struct {
 | 
						|
	X, Y int
 | 
						|
}
 | 
						|
 | 
						|
// Area represents the visible area for SSE updates
 | 
						|
type Area struct {
 | 
						|
	X, Y, Width, Height int
 | 
						|
}
 | 
						|
 | 
						|
// Contains checks if a point is within the SSE area
 | 
						|
func (a Area) Contains(x int, y int) bool {
 | 
						|
	return x >= a.X && x <= a.X+a.Width && y >= a.Y && y <= a.Y+a.Height
 | 
						|
}
 | 
						|
 | 
						|
// SpatialHashMap implements spatial hashing for efficient point storage and retrieval
 | 
						|
type SpatialHashMap struct {
 | 
						|
	mu sync.RWMutex
 | 
						|
	db *SQLiteEngine
 | 
						|
}
 | 
						|
 | 
						|
// NewSpatialHashMap creates a new spatial hash map
 | 
						|
func NewSpatialHashMap(dbPath string) (*SpatialHashMap, error) {
 | 
						|
	db, err := CreateSQLite(dbPath)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return &SpatialHashMap{
 | 
						|
		db: db,
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *SpatialHashMap) InitSchema() error {
 | 
						|
	err := s.db.Execute(
 | 
						|
		`CREATE TABLE IF NOT EXISTS spatial_hashmap (
 | 
						|
			cluster_x INTEGER NOT NULL,
 | 
						|
			cluster_y INTEGER NOT NULL,
 | 
						|
			x INTEGER NOT NULL,
 | 
						|
			y INTEGER NOT NULL,
 | 
						|
			PRIMARY KEY (cluster_x, cluster_y, x, y)) WITHOUT ROWID`)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// getHash calculates the hash coordinates for a given point
 | 
						|
func (s *SpatialHashMap) getHash(x, y int) Point {
 | 
						|
	return Point{X: x / ChunkSize, Y: y / ChunkSize}
 | 
						|
}
 | 
						|
 | 
						|
// Insert adds a point to the spatial hash map
 | 
						|
func (s *SpatialHashMap) Insert(x, y int) error {
 | 
						|
	s.mu.Lock()
 | 
						|
	defer s.mu.Unlock()
 | 
						|
 | 
						|
	key := s.getHash(x, y)
 | 
						|
	err := s.db.Execute(
 | 
						|
		"INSERT INTO spatial_hashmap (cluster_x, cluster_y, x, y) VALUES (?, ?, ?, ?)",
 | 
						|
		key.X, key.Y, x, y)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Remove removes a point from the spatial hash map
 | 
						|
func (s *SpatialHashMap) Remove(x, y int) error {
 | 
						|
	s.mu.Lock()
 | 
						|
	defer s.mu.Unlock()
 | 
						|
 | 
						|
	key := s.getHash(x, y)
 | 
						|
	err := s.db.Execute(
 | 
						|
		"DELETE FROM spatial_hashmap WHERE cluster_x = ? AND cluster_y = ? AND x = ? AND y = ?",
 | 
						|
		key.X, key.Y, x, y)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// GetLocalPoints returns all points within the given bounding box
 | 
						|
func (s *SpatialHashMap) GetLocalPoints(area Area) []Point {
 | 
						|
	hashStart, hashEnd := s.getHash(area.X, area.Y), s.getHash(area.X+area.Width, area.Y+area.Height)
 | 
						|
 | 
						|
	rows, err := s.db.Query(
 | 
						|
		"SELECT x, y FROM spatial_hashmap WHERE cluster_x BETWEEN ? AND ? AND cluster_y BETWEEN ? AND ?",
 | 
						|
		hashStart.X, hashEnd.X, hashStart.Y, hashEnd.Y)
 | 
						|
	if err != nil {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	defer rows.Close()
 | 
						|
 | 
						|
	localPoints := make([]Point, 0)
 | 
						|
	for rows.Next() {
 | 
						|
		var x, y int
 | 
						|
		if err := rows.Scan(&x, &y); err != nil {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		localPoints = append(localPoints, Point{X: x, Y: y})
 | 
						|
	}
 | 
						|
	return localPoints
 | 
						|
}
 | 
						|
 | 
						|
func (s *SpatialHashMap) Close() error {
 | 
						|
	if s.db != nil {
 | 
						|
		return s.db.Close()
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 |