func Distance(g1, g2 Geometry) (float64, bool) {
	if Intersects(g1, g2) {
		return 0, true
	}
	xys1, lns1 := extractXYsAndLines(g1)
	xys2, lns2 := extractXYsAndLines(g2)
	if len(xys1)+len(lns1) > len(xys2)+len(lns2) {
		xys1, xys2 = xys2, xys1
		lns1, lns2 = lns2, lns1
	}
	tr := loadTree(xys2, lns2)
	minDist := math.Inf(+1)
	searchBody := func(
		env Envelope,
		recordID int,
		xyDist func(int) float64,
		lnDist func(int) float64,
	) error {
		xyIdx := recordID - 1
		lnIdx := -recordID - 1
		var recordEnv Envelope
		if recordID > 0 {
			recordEnv = xys2[xyIdx].uncheckedEnvelope()
		} else {
			recordEnv = lns2[lnIdx].uncheckedEnvelope()
		}
		if d, ok := recordEnv.Distance(env); ok && d > minDist {
			return rtree.Stop
		}
		if recordID > 0 {
			minDist = fastMin(minDist, xyDist(xyIdx))
		} else {
			minDist = fastMin(minDist, lnDist(lnIdx))
		}
		return nil
	}
	for _, xy := range xys1 {
		xyEnv := xy.uncheckedEnvelope()
		tr.PrioritySearch(xy.box(), func(recordID int) error {
			return searchBody(
				xyEnv,
				recordID,
				func(i int) float64 { return distBetweenXYs(xy, xys2[i]) },
				func(i int) float64 { return distBetweenXYAndLine(xy, lns2[i]) },
			)
		})
	}
	for _, ln := range lns1 {
		lnEnv := ln.uncheckedEnvelope()
		tr.PrioritySearch(ln.box(), func(recordID int) error {
			return searchBody(
				lnEnv,
				recordID,
				func(i int) float64 { return distBetweenXYAndLine(xys2[i], ln) },
				func(i int) float64 { return distBetweenLineAndLine(lns2[i], ln) },
			)
		})
	}
	if math.IsInf(minDist, +1) {
		return 0, false
	}
	return minDist, true
}
Distance calculates the shortest distance (using the Euclidean metric)
between two geometries. If either geometry is empty, then false is returned
and the distance is not calculated.
package geom
import (
	"fmt"
	"math"
	"github.com/peterstace/simplefeatures/rtree"
)