// Copyright © Joerg Battermann 2014, Matt Hunt 2017
using GeoJSON.Text.Converters;
using GeoJSON.Text.CoordinateReferenceSystem;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text.Json.Serialization;
namespace GeoJSON.Text
{
///
/// Base class for all IGeometryObject implementing types
///
public abstract class GeoJSONObject : IGeoJSONObject, IEqualityComparer, IEquatable
{
internal static readonly DoubleTenDecimalPlaceComparer DoubleComparer = new();
///
/// Gets or sets the (optional)
/// Bounding Boxes.
///
///
/// The value of must be a 2*n array where n is the number of dimensions represented in
/// the
/// contained geometries, with the lowest values for all axes followed by the highest values.
/// The axes order of a bbox follows the axes order of geometries.
/// In addition, the coordinate reference system for the bbox is assumed to match the coordinate reference
/// system of the GeoJSON object of which it is a member.
///
[JsonPropertyName("bbox")]
[JsonConverter(typeof(BoundingBoxConverter))]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double[] BoundingBoxes { get; set; }
///
/// Gets or sets the (optional)
///
/// Coordinate Reference System
/// Object.
///
///
///
/// The Coordinate Reference System Objects.
///
[JsonPropertyName("crs")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
[JsonConverter(typeof(CrsConverter))]
public ICRSObject CRS { get; set; }
///
/// The (mandatory) type of the
/// GeoJSON Object.
///
[JsonPropertyName("type")]
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public abstract GeoJSONObjectType Type { get; }
#region IEqualityComparer, IEquatable
///
/// Determines whether the specified object is equal to the current object
///
public override bool Equals(object obj)
{
return Equals(this, obj as GeoJSONObject);
}
///
/// Determines whether the specified object is equal to the current object
///
public bool Equals(GeoJSONObject other)
{
return Equals(this, other);
}
///
/// Determines whether the specified object instances are considered equal
///
public bool Equals(GeoJSONObject left, GeoJSONObject right)
{
if (ReferenceEquals(left, right))
{
return true;
}
if (right is null)
{
return false;
}
if (left.Type != right.Type)
{
return false;
}
if (!Equals(left.CRS, right.CRS))
{
return false;
}
var leftIsNull = left.BoundingBoxes is null;
var rightIsNull = right.BoundingBoxes is null;
var bothAreMissing = leftIsNull && rightIsNull;
if (bothAreMissing || leftIsNull != rightIsNull)
{
return bothAreMissing;
}
return left.BoundingBoxes.SequenceEqual(right.BoundingBoxes, DoubleComparer);
}
///
/// Determines whether the specified object instances are considered equal
///
public static bool operator ==(GeoJSONObject left, GeoJSONObject right)
{
if (ReferenceEquals(left, right))
{
return true;
}
if (right is null)
{
return false;
}
return left.Equals(right);
}
///
/// Determines whether the specified object instances are not considered equal
///
public static bool operator !=(GeoJSONObject left, GeoJSONObject right)
{
return !(left == right);
}
///
/// Returns the hash code for this instance
///
public override int GetHashCode()
{
return ((int)Type).GetHashCode();
}
///
/// Returns the hash code for the specified object
///
public int GetHashCode(GeoJSONObject obj)
{
return obj.GetHashCode();
}
#endregion
}
}