A lightweight and efficient Go library for processing point cloud data in PCD (Point Cloud Data) and BIN formats. This library provides comprehensive tools for reading, writing, transforming, and analyzing point cloud data.
-
Multiple Format Support
- PCD file format (ASCII and Binary)
- Binary point cloud format (BIN)
- LZF compression support for PCD files
-
Point Cloud Operations
- Filtering by bounds and intensity
- Downsampling (uniform and voxel-based)
- Outlier removal using statistical analysis
- Merging multiple point clouds
- Cloning and validation
-
Transformations
- Translation
- Scaling
- Rotation (X, Y, Z axes)
- Custom transformation matrices
-
Analysis Tools
- Statistics (min, max, average, standard deviation)
- Centroid calculation
- Bounding box computation
- Point-to-point distance calculation
- XY area estimation
-
Memory Efficient
- Uses
unsafe.Slicefor zero-copy byte-to-float conversions - Optimized for large point cloud datasets
- Uses
go get github.com/flywave/go-pcdpackage main
import (
"fmt"
"os"
"github.com/flywave/go-pcd"
)
func main() {
// Open PCD file
file, err := os.Open("input.pcd")
if err != nil {
panic(err)
}
defer file.Close()
// Decode PCD
pcd, err := pcd.DecodePcd(file)
if err != nil {
panic(err)
}
fmt.Printf("Loaded %d points\n", pcd.PointCount())
}package main
import (
"github.com/flywave/go-pcd"
)
func main() {
// Create a new PCD
pcd := &pcd.Pcd{}
// Add points
pcd.AddPoint(pcd.Point{X: 1.0, Y: 2.0, Z: 3.0, R: 0.5})
pcd.AddPoint(pcd.Point{X: 4.0, Y: 5.0, Z: 6.0, R: 0.8})
// Save to file
err := pcd.SaveToFile("output.pcd")
if err != nil {
panic(err)
}
}package main
import (
"os"
"github.com/flywave/go-pcd"
)
func main() {
// Read BIN file
file, err := os.Open("input.bin")
if err != nil {
panic(err)
}
defer file.Close()
bin, err := pcd.DecodeBin(file)
if err != nil {
panic(err)
}
// Convert to PCD
pcd, err := bin.ToPcd()
if err != nil {
panic(err)
}
// Save as PCD
err = pcd.SaveToFile("output.pcd")
if err != nil {
panic(err)
}
}// Filter by bounds
filtered := pcd.FilterByBounds(0, 10, 0, 10, 0, 10)
// Filter by intensity
intensityFiltered := pcd.FilterByIntensity(0.3, 0.9)
// Custom filter
customFiltered := pcd.Filter(func(p pcd.Point) bool {
return p.Z > 5.0
})// Translate
translated := pcd.Translate(1.0, 2.0, 3.0)
// Scale
scaled := pcd.Scale(2.0, 2.0, 2.0)
// Rotate around Z axis
rotated := pcd.RotateZ(3.14159 / 4) // 45 degrees
// Custom transformation matrix
matrix := [4][4]float32{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
}
transformed := pcd.Transform(matrix)// Uniform downsampling
downsampled := pcd.Downsample(2) // Keep every 2nd point
// Voxel grid downsampling
voxelDownsampled := pcd.VoxelDownsample(0.1) // 0.1m voxel size// Get statistics
min, max, avg, std := pcd.GetStatistics()
fmt.Printf("Min: X=%.2f Y=%.2f Z=%.2f\n", min.X, min.Y, min.Z)
fmt.Printf("Max: X=%.2f Y=%.2f Z=%.2f\n", max.X, max.Y, max.Z)
fmt.Printf("Avg: X=%.2f Y=%.2f Z=%.2f\n", avg.X, avg.Y, avg.Z)
fmt.Printf("Std: X=%.2f Y=%.2f Z=%.2f\n", std.X, std.Y, std.Z)
// Get centroid
centroid := pcd.GetCentroid()
fmt.Printf("Centroid: X=%.2f Y=%.2f Z=%.2f\n", centroid.X, centroid.Y, centroid.Z)
// Get dimensions
width, height, depth := pcd.GetDimensions()
fmt.Printf("Dimensions: %.2f x %.2f x %.2f\n", width, height, depth)
// Get bounds
min, max := pcd.GetBounds()
fmt.Printf("Bounds: Min(%.2f, %.2f, %.2f) Max(%.2f, %.2f, %.2f)\n",
min.X, min.Y, min.Z, max.X, max.Y, max.Z)p1 := pcd.Point{X: 1.0, Y: 2.0, Z: 3.0, R: 0.5}
p2 := pcd.Point{X: 4.0, Y: 6.0, Z: 8.0, R: 0.8}
// Calculate distance
distance := p1.DistanceTo(p2)
// Add points
sum := p1.Add(p2)
// Subtract points
diff := p2.Subtract(p1)
// Scale point
scaled := p1.Scale(2.0)pcd1 := &pcd.Pcd{}
pcd1.AddPoint(pcd.Point{X: 1.0, Y: 2.0, Z: 3.0, R: 0.5})
pcd2 := &pcd.Pcd{}
pcd2.AddPoint(pcd.Point{X: 4.0, Y: 5.0, Z: 6.0, R: 0.8})
// Merge point clouds
merged := pcd1.Merge(pcd2)// Remove outliers using statistical analysis
cleaned := pcd.RemoveOutliers(10, 1.5)
// meanK: number of neighbors to analyze
// stdMultiplier: standard deviation multiplierRepresents a 3D point with intensity.
type Point struct {
X, Y, Z float32 // 3D coordinates
R float32 // Intensity/reflectance
}Point Cloud Data structure.
type Pcd struct {
PointCloud
}Binary point cloud structure.
type Bin struct {
PointCloud
}DecodePcd(r io.Reader) (*Pcd, error)- Decode PCD from readerEncode(w io.Writer) error- Encode PCD to writerDecodeBin(r io.Reader) (*Bin, error)- Decode BIN from readerEncode(w io.Writer) error- Encode BIN to writer
FilterByBounds(minX, maxX, minY, maxY, minZ, maxZ float32) *PcdFilterByIntensity(minR, maxR float32) *PcdDownsample(step int) *PcdVoxelDownsample(voxelSize float32) *PcdTranslate(dx, dy, dz float32) *PcdScale(sx, sy, sz float32) *PcdRotateX(angle float32) *PcdRotateY(angle float32) *PcdRotateZ(angle float32) *PcdMerge(other *Pcd) *PcdRemoveOutliers(meanK int, stdMultiplier float32) *Pcd
GetStatistics() (min, max, avg, std Point)GetCentroid() PointGetBounds() (min, max Point)GetDimensions() (width, height, depth float32)
DistanceTo(other Point) float32Add(other Point) PointSubtract(other Point) PointScale(factor float32) Point
Run the test suite:
go test -v ./...- Go 1.17 or higher
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
- PCD format specification from Point Cloud Library (PCL)
- LZF compression by zhuyie/golzf