diff --git a/pyresample/boundary/__init__.py b/pyresample/boundary/__init__.py
index 258952af..2e420646 100644
--- a/pyresample/boundary/__init__.py
+++ b/pyresample/boundary/__init__.py
@@ -17,6 +17,7 @@
# along with this program. If not, see .
"""The Boundary classes."""
+from pyresample.boundary.boundary_sides import BoundarySides # noqa
from pyresample.boundary.legacy_boundary import ( # noqa
AreaBoundary,
AreaDefBoundary,
diff --git a/pyresample/boundary/boundary_sides.py b/pyresample/boundary/boundary_sides.py
new file mode 100644
index 00000000..9722d90d
--- /dev/null
+++ b/pyresample/boundary/boundary_sides.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2014-2023 Pyresample developers
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+"""Define the BoundarySides class."""
+
+import logging
+
+import numpy as np
+
+logger = logging.getLogger(__name__)
+
+
+class BoundarySides:
+ """A class to represent the sides of an area boundary.
+
+ The sides are stored as a tuple of 4 numpy arrays, each representing the
+ coordinate (geographic or projected) of the vertices of the boundary side.
+ The sides must be stored in the order (top, right, left, bottom),
+ which refers to the side position with respect to the coordinate array.
+ The first row of the coordinate array correspond to the top side, the last row to the bottom side,
+ the first column to the left side and the last column to the right side.
+ Please note that the last vertex of each side must be equal to the first vertex of the next side.
+ """
+ __slots__ = ['_sides']
+
+ def __init__(self, sides: tuple[ArrayLike, ArrayLike, ArrayLike, ArrayLike]):
+ """Initialize the BoundarySides object."""
+ if len(sides) != 4 or not all(isinstance(side, np.ndarray) and side.ndim == 1 for side in sides):
+ raise ValueError("Sides must be a list of four numpy arrays.")
+
+ if not all(np.array_equal(sides[i][-1], sides[(i + 1) % 4][0]) for i in range(4)):
+ raise ValueError("The last element of each side must be equal to the first element of the next side.")
+
+ self._sides = tuple(sides) # Store as a tuple
+
+ @property
+ def top(self):
+ """Return the vertices of the top side."""
+ return self._sides[0]
+
+ @property
+ def right(self):
+ """Return the vertices of the right side."""
+ return self._sides[1]
+
+ @property
+ def bottom(self):
+ """Return the vertices of the bottom side."""
+ return self._sides[2]
+
+ @property
+ def left(self):
+ """Return the vertices of the left side."""
+ return self._sides[3]
+
+ @property
+ def vertices(self):
+ """Return the vertices of the concatenated sides.
+
+ Note that the last element of each side is discarded to avoid duplicates.
+ """
+ return np.concatenate([side[:-1] for side in self._sides])
+
+ def __iter__(self):
+ """Return an iterator over the sides."""
+ return iter(self._sides)
+
+ def __getitem__(self, index):
+ """Return the side at the given index."""
+ if not isinstance(index, int) or not 0 <= index < 4:
+ raise IndexError("Index must be an integer from 0 to 3.")
+ return self._sides[index]
diff --git a/pyresample/test/test_boundary/test_boundary_sides.py b/pyresample/test/test_boundary/test_boundary_sides.py
new file mode 100644
index 00000000..58051b5d
--- /dev/null
+++ b/pyresample/test/test_boundary/test_boundary_sides.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# pyresample, Resampling of remote sensing image data in python
+#
+# Copyright (C) 2010-2022 Pyresample developers
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+"""Test the BoundarySides objects."""
+
+import numpy as np
+import pytest
+
+from pyresample.boundary import BoundarySides
+
+
+class TestBoundarySides:
+ """Test suite for the BoundarySides class with 1D numpy arrays for sides."""
+
+ def test_initialization_valid_input(self):
+ """Test initialization with valid 1D numpy array inputs."""
+ sides = [np.array([1, 2, 3]), # top
+ np.array([3, 4, 5]), # right
+ np.array([5, 6, 7]), # bottom
+ np.array([7, 8, 1])] # left
+ boundary = BoundarySides(sides)
+ assert all(np.array_equal(boundary[i], sides[i]) for i in range(4))
+
+ def test_initialization_invalid_input(self):
+ """Test initialization with invalid inputs, such as wrong number of sides or non-1D arrays."""
+ with pytest.raises(ValueError):
+ BoundarySides([np.array([1, 2]), # Invalid number of sides
+ np.array([2, 3])])
+
+ with pytest.raises(ValueError):
+ BoundarySides([np.array([1, 2]), # Non-1D arrays
+ np.array([[2, 3], [4, 5]]),
+ np.array([5, 6]),
+ np.array([6, 7])])
+
+ with pytest.raises(ValueError):
+ BoundarySides([np.array([1, 2]), # Invalid side connection
+ np.array([3, 4]),
+ np.array([4, 6]),
+ np.array([6, 1])])
+
+ def test_property_accessors(self):
+ """Test property accessors with 1D numpy arrays."""
+ sides = [np.array([1, 2, 3]), # top
+ np.array([3, 4, 5]), # right
+ np.array([5, 6, 7]), # bottom
+ np.array([7, 8, 1])] # left
+ boundary = BoundarySides(sides)
+ assert np.array_equal(boundary.top, sides[0])
+ assert np.array_equal(boundary.right, sides[1])
+ assert np.array_equal(boundary.bottom, sides[2])
+ assert np.array_equal(boundary.left, sides[3])
+
+ def test_vertices_property(self):
+ """Test the vertices property with concatenated 1D numpy arrays."""
+ sides = [np.array([1, 2, 3]), # top
+ np.array([3, 4, 5]), # right
+ np.array([5, 6, 7]), # bottom
+ np.array([7, 8, 1])] # left
+ boundary = BoundarySides(sides)
+ expected_vertices = np.array([1, 2, 3, 4, 5, 6, 7, 8])
+ assert np.array_equal(boundary.vertices, expected_vertices)
+
+ def test_iteration(self):
+ """Test iteration over the 1D numpy array sides."""
+ sides = [np.array([1, 2, 3]), # top
+ np.array([3, 4, 5]), # right
+ np.array([5, 6, 7]), # bottom
+ np.array([7, 8, 1])] # left
+ boundary = BoundarySides(sides)
+ for i, side in enumerate(boundary):
+ assert np.array_equal(side, sides[i])
+
+ def test_indexing_valid(self):
+ """Test valid indexing with 1D numpy arrays."""
+ sides = [np.array([1, 2, 3]), # top
+ np.array([3, 4, 5]), # right
+ np.array([5, 6, 7]), # bottom
+ np.array([7, 8, 1])] # left
+ boundary = BoundarySides(sides)
+ for i in range(4):
+ assert np.array_equal(boundary[i], sides[i])
+
+ def test_indexing_invalid(self):
+ """Test indexing with invalid indices."""
+ sides = [np.array([1, 2, 3]), # top
+ np.array([3, 4, 5]), # right
+ np.array([5, 6, 7]), # bottom
+ np.array([7, 8, 1])] # left
+ boundary = BoundarySides(sides)
+ with pytest.raises(IndexError):
+ boundary[4] # Invalid index