You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: affine_transforms_test.go
    path of file: ./repos/cockroach/pkg/geo/geomfn
    
    the code of the file until where you have to start completion: // Copyright 2020 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package geomfn

import (
	"errors"
	"math"
	"testing"

	"github.com/cockroachdb/cockroach/pkg/geo"
	"github.com/cockroachdb/cockroach/pkg/geo/geotest"
	"github.com/stretchr/testify/require"
	"github.com/twpayne/go-geom"
)

func TestTranslate(t *testing.T) {
	testCases := []struct {
		desc     string
		input    geom.T
		deltas   []float64
		expected geom.T
	}{
		{
			desc:     "translate a 2D point",
			input:    geom.NewPointFlat(geom.XY, []float64{10, 10}),
			deltas:   []float64{5, -5},
			expected: geom.NewPointFlat(geom.XY, []float64{15, 5}),
		},
		{
			desc:     "translate a 2D line string",
			input:    geom.NewLineStringFlat(geom.XY, []float64{10, 15, 20, 30}),
			deltas:   []float64{1, 5},
			expected: geom.NewLineStringFlat(geom.XY, []float64{11, 20, 21, 35}),
		},
		{
			desc:     "translate a 2D polygon",
			input:    geom.NewPolygonFlat(geom.XY, []float64{0, 0, 5, 5, 0, 10, 0, 0}, []int{8}),
			deltas:   []float64{1, 1},
			expected: geom.NewPolygonFlat(geom.XY, []float64{1, 1, 6, 6, 1, 11, 1, 1}, []int{8}),
		},
		{
			desc:     "translate multiple 2D points",
			input:    geom.NewMultiPointFlat(geom.XY, []float64{5, 10, -30, 40}),
			deltas:   []float64{1, 0.5},
			expected: geom.NewMultiPointFlat(geom.XY, []float64{6, 10.5, -29, 40.5}),
		},
		{
			desc:     "translate multiple 2D line strings",
			input:    geom.NewMultiLineStringFlat(geom.XY, []float64{1, 1, 2, 2, 3, 3, 4, 4}, []int{4, 8}),
			deltas:   []float64{.1, .1},
			expected: geom.NewMultiLineStringFlat(geom.XY, []float64{1.1, 1.1, 2.1, 2.1, 3.1, 3.1, 4.1, 4.1}, []int{4, 8}),
		},
		{
			desc:     "translate empty 2D line string",
			input:    geom.NewLineString(geom.XY),
			deltas:   []float64{1, 1},
			expected: geom.NewLineString(geom.XY),
		},
		{
			desc:     "translate empty 2D polygon",
			input:    geom.NewPolygon(geom.XY),
			deltas:   []float64{1, 1},
			expected: geom.NewPolygon(geom.XY),
		},
		{
			desc: "translate non-empty 2D collection",
			input: geom.NewGeometryCollection().MustPush(
				geom.NewPointFlat(geom.XY, []float64{10, 10}),
				geom.NewLineStringFlat(geom.XY, []float64{0, 0, 5, 5}),
				geom.NewMultiPointFlat(geom.XY, []float64{0, 0, -5, -5, -10, -10}),
			),
			deltas: []float64{1, -1},
			expected: geom.NewGeometryCo
    
func TestRotateWithPointOrigin(t *testing.T) {
	tests := []struct {
		desc            string
		inputGeom       geom.T
		inputRotRadians float64
		inputPointGeom  geom.T
		wantGeom        geom.T
		wantErrStr      string
	}{
		{
			desc:            "rotate a 2D point where angle is 2Pi, the input geom is 10 10 and point geom is 5 5",
			inputGeom:       geom.NewPointFlat(geom.XY, []float64{10, 10}),
			inputRotRadians: 2 * math.Pi,
			inputPointGeom:  geom.NewPointFlat(geom.XY, []float64{5, 5}),
			wantGeom:        geom.NewPointFlat(geom.XY, []float64{10, 10}),
		},
		{
			desc:            "rotate a 2D point where angle is Pi, the input geom is 10 9 and the point geom is 7 5",
			inputGeom:       geom.NewPointFlat(geom.XY, []float64{10, 9}),
			inputRotRadians: math.Pi,
			inputPointGeom:  geom.NewPointFlat(geom.XY, []float64{7, 5}),
			wantGeom:        geom.NewPointFlat(geom.XY, []float64{4, 1}),
		},
		{
			desc:            "rotate a 2D point where angle is Pi, the input geom is 10.11 10.55 and the point geom is 5 5",
			inputGeom:       geom.NewPointFlat(geom.XY, []float64{10.11, 10.55}),
			inputRotRadians: math.Pi,
			inputPointGeom:  geom.NewPointFlat(geom.XY, []float64{5, 5}),
			wantGeom:        geom.NewPointFlat(geom.XY, []float64{-0.11, -0.55}),
		},
		{
			desc:            "rotate a 2D line string where angle is Pi, the input geom is 1 5, 5 1 and the point geom is 5 5",
			inputGeom:       geom.NewLineStringFlat(geom.XY, []float64{1, 5, 5, 1}),
			inputRotRadians: math.Pi,
			inputPointGeom:  geom.NewPointFlat(geom.XY, []float64{5, 5}),
			wantGeom:        geom.NewLineStringFlat(geom.XY, []float64{9, 5, 5, 9}),
		},
		{
			desc:            "rotate a 2D line string where angle is Pi/4, the input geom is 1 5, 5 1 and the point geom is 5 5",
			inputGeom:       geom.NewLineStringFlat(geom.XY, []float64{1, 5, 5, 1}),
			inputRotRadians: math.Pi / 4,
			inputPointGeom:  geom.NewPointFlat(geom.XY, []float64{5, 5}),
			wantGeom:        geom.NewLineStringFlat(geom.XY, []float64{2.17157287525381, 2.17157287525381, 7.82842712474619, 2.17157287525381}),
		},
		{
			desc:            "rotate a 2D line string where angle is 2Pi, the input geom is 1 5, 5 1 and the point geom is 4 8",
			inputGeom:       geom.NewLineStringFlat(geom.XY, []float64{1, 5, 5, 1}),
			inputRotRadians: 2 * math.Pi,
			inputPointGeom:  geom.NewPointFlat(geom.XY, []float64{4, 8}),
			wantGeom:        geom.NewLineStringFlat(geom.XY, []float64{1, 5, 5, 1}),
		},
		{
			desc:            "rotate multiple 2D points",
			inputGeom:       geom.NewMultiPointFlat(geom.XY, []float64{10, 10, 20, 20}),
			inputRotRadians: math.Pi / 2,
			inputPointGeom:  geom.NewPointFlat(geom.XY, []float64{10.55, 8.88}),
			wantGeom:        geom.NewMultiPointFlat(geom.XY, []float64{9.43, 8.33, -0.57, 18.33}),
		},
		{
			desc:            "rotate polygon strings",
			inputGeom:       geom.NewPolygonFlat(geom.XY, []float64{0, 0, 4, 0, 4, 4, 0, 4, 0, 0, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1}, []int{10, 20}),
			inputRotRadians: math.Pi,
			inputPointGeom:  geom.NewPointFlat(geom.XY, []float64{9, 9}),
			wantGeom:        geom.NewPolygonFlat(geom.XY, []float64{18, 18, 14, 18, 14, 14, 18, 14, 18, 18, 17, 17, 16, 17, 16, 16, 17, 16, 17, 17}, []int{10, 20}),
		},
		{
			desc:            "rotate a 2D point where angle is Pi, the input geom is 10 9 and the line string geom is 7 5, 5 5",
			inputGeom:       geom.NewPointFlat(geom.XY, []float64{10, 9}),
			inputRotRadians: math.Pi,
			inputPointGeom:  geom.NewLineStringFlat(geom.XY, []float64{7, 5, 5, 5}),
			wantGeom:        geom.NewPointFlat(geom.XY, []float64{10, 9}),
			wantErrStr:      "origin is not a POINT",
		},
		{
			desc:            "rotate a 2D point where point origin is empty",
			inputGeom:       geom.NewPointFlat(geom.XY, []float64{10, 9}),
			inputRotRadians: math.Pi,
			inputPointGeom:  geom.NewPointEmpty(geom.XY),
			wantGeom:        geom.NewPointFlat(geom.XY, []float64{10, 9}),
			wantErrStr:      "origin is an empty point",
		},
	}
	for _, tt := range tests {
		t.Run(tt.desc, func(t *testing.T) {
			geometry, err := geo.MakeGeometryFromGeomT(tt.inputGeom)
			require.NoError(t, err)

			pointGeometry, err := geo.MakeGeometryFromGeomT(tt.inputPointGeom)
			require.NoError(t, err)

			got, err := RotateWithPointOrigin(geometry, tt.inputRotRadians, pointGeometry)
			if tt.wantErrStr != "" {
				require.EqualError(t, err, tt.wantErrStr)
			} else {
				require.NoError(t, err)
				geotest.RequireGeometryInEpsilon(t, requireGeometryFromGeomT(t, tt.wantGeom), got, 1e-5)
			}
		})
	}
}