This repository was archived by the owner on Jun 22, 2023. It is now read-only.
Remove redundant interface members #67
Labels
breaking change
Doing this would break either source or binary compatibility with existing versions.
Milestone
Every member defined on an interface represents an added cost to whoever is ultimately going to implement it. Some of our interfaces have gotten way out of hand, and #30* seeks to help with that by segregating the interfaces more so that the implementer doesn't have to account for everything under the sun.
However, we could get some "quick wins" towards usability by removing some members that are outright redundant with other members already on the same interface (adding extension methods in their place where appropriate to avoid harming usability).
I propose that we try to simplify as much of this list as we reasonably can...
ICoordinateBuffer
AddCoordinate(...)
is redundant withInsertCoordinate(Count, ...)
, but can we just get rid of this interface?ICoordinateSequence
Ordinate
/Ordinates
and friends... that's a whole other topic of its own.GetCoordinateCopy(i)
is equivalent toGetCoordinate(i, CreateCoordinate())
.ToCoordinateArray()
is a bunch ofGetCoordinateCopy(i)
calls to initializenew Coordinate[Count]
.ExpandEnvelope(env)
is a bunch of calls toenv.ExpandToInclude(GetX(i), GetY(i))
.ICoordinateSequenceFactory
Again, leaving out
Ordinate
/Ordinates
and friends.ICoordinateSequence Create(int size, int dimension, int measures)
is all that implementations should need to care about implementing."Create it as a copy of this other thing" can have a major impact on performance for pretty much every implementation (there's almost always a better way to copy from an instance of the same type), however, I think we can satisfy that need almost as well with a new "default interface method"*:
*I know that we can't do default interface methods properly, but there's a way to cheat at it that's almost as good... instead of a true "default interface method", we can use an extension method with a helper interface... to give an idea, an interface with a "default method" that we wish we could write like this:
could be delivered like this:
ICurve
IsClosed
is the same as checking whetherStartPoint
andEndPoint
are equal.IsRing
is apparentlyIsClosed && IsSimple
, according to its single implementation that isn't called by anyone I can discover right now.IGeometry
Strict redundancies
SRID
isFactory.SRID
.GeometryType
looks likeGetType().Name
???Envelope
isFactory.ToGeometry(EnvelopeInternal)
.Normalized()
isCopy().Normalize()
+ return the normalized copy.EqualsExact(g)
isEqualsExact(g, 0)
.EqualsNormalized(g)
isNormalized().EqualsExact(g.Normalized())
.PointOnSurface
isInteriorPoint
.x.Within(y)
isy.Contains(x)
.x.CoveredBy(y)
isy.Covers(x)
.x.Disjoint(y)
is!x.Intersects(y)
.Relate(g, somePattern)
isRelate(g).Matches(somePattern)
.Buffer(double, IBufferParameters)
is the onlyBuffer
method we need.IBufferParameters
not to be an interface...Can be implemented via a call to
Apply(...)
int NumGeometries
int NumPoints
Coordinate Coordinate
Coordinate[] Coordinates
double[] GetOrdinates(Ordinate)
Dimension Dimension
(butOgcGeometryType
will often be enough)IGeometry Envelope
Envelope EnvelopeInternal
bool IsEmpty
Can be implemented via
Relate(g)
, though there's often a decent way to short-circuit.Contains
/Within
Covers
/CoveredBy
Intersects
/Disjoint
Touches
Crosses
Overlaps
EqualsTopologically
IGeometryCollection
int Count
isNumGeometries
this[int]
isGetGeometryN
IGeometry[] Geometries
also could bethis.ToArray()
if we're OK with no longer defining it as a view of the underlying data... not exactly a discussion for here though.IGeometryFactory
These methods are variants of other methods invoke those other methods with some sort of "empty":
CreatePoint()
CreateLineString()
CreateLinearRing()
CreatePolygon()
CreatePolygon(ILinearRing)
CreateMultiPoint()
CreateMultiLineString()
CreateMultiPolygon()
CreateGeometryCollection()
These methods are variants of other
ICoordinateSequence
methods viaCoordinateSequenceFactory
:CreatePoint(Coordinate)
CreateLineString(Coordinate[])
CreateLinearRing(Coordinate[])
CreatePolygon(Coordinate[])
CreateMultiPointFromCoords(Coordinate[])
Finally,
CreatePolygon(ICoordinateSequence)
isCreatePolygon(CreateLineString(seq))
ILineString
GetCoordinateN(i)
isCoordinateSequence.GetCoordinate(i)
GetPointN(i)
isFactory.CreatePoint(GetCoordinateN(i))
IMultiCurve
bool IsClosed
is!IsEmpty && Cast<ICurve>().All(g => g.IsClosed)
IPoint
X
isCoordinateSequence.GetX(0)
. Same for Y, Z, M.IPolygon
Same idea as in
IGeometryCollection
, we only need either the array or the Num +ExteriorRing
isShell
.ILineString[] InteriorRings
isHoles.ToArray<ILineString>()
int NumInteriorRings
/GetInteriorRingN(int)
come fromHoles
, or vice-versa if we don't want to keep definingHoles
as a view of the underlying data.IPrecisionModel
bool IsFloating
,int MaximumSignificantDigits
, andvoid MakePrecise(Coordinate)
are all defined to be the same as their NTS implementations.IGeometryServices
CreatePrecisionModel(IPrecisionModel)
is one of the two other overloads depending on the type.All
CreateGeometryFactory
overloads are equivalent toCreateGeometryFactory(IPrecisionModel, int, ICoordinateSequenceFactory)
, filling in the defaults from properties where missing.The text was updated successfully, but these errors were encountered: