1 /// Provides a wrapper around a `mg_point_2d`.
2 module memgraph.point2d;
3 
4 import memgraph.mgclient, memgraph.detail, memgraph.value, memgraph.enums;
5 
6 /// Represents a single location in 2-dimensional space.
7 ///
8 /// Contains SRID along with its x and y coordinates.
9 struct Point2d {
10 
11 	/// Create a deep copy of `other` point 2d.
12 	this(inout ref Point2d other) {
13 		this(mg_point_2d_copy(other.ptr));
14 	}
15 
16 	/// Create a point 2d from a Value.
17 	this(inout ref Value value) {
18 		assert(value.type == Type.Point2d);
19 		this(mg_point_2d_copy(mg_value_point_2d(value.ptr)));
20 	}
21 
22 	/// Assigns a point 2d to another. The target of the assignment gets detached from
23 	/// whatever point 2d it was attached to, and attaches itself to the new point 2d.
24 	ref Point2d opAssign(Point2d rhs) @safe return {
25 		import std.algorithm.mutation : swap;
26 		swap(this, rhs);
27 		return this;
28 	}
29 
30 	/// Return a printable string representation of this time.
31 	string toString() const {
32 		import std.conv : to;
33 		return to!string(srid) ~ " " ~ to!string(x) ~ " " ~ to!string(y);
34 	}
35 
36 	/// Compares this point 2d with `other`.
37 	/// Return: true if same, false otherwise.
38 	bool opEquals(const ref Point2d other) const {
39 		return Detail.arePoint2dsEqual(ptr_, other.ptr);
40 	}
41 
42 	/// Returns SRID of the 2D point.
43 	long srid() const { return mg_point_2d_srid(ptr_); }
44 	/// Returns the x coordinate of the 2D point.
45 	double x() const { return mg_point_2d_x(ptr_); }
46 	/// Returns the y coordinate of the 2D point.
47 	double y() const { return mg_point_2d_y(ptr_); }
48 
49 	this(this) {
50 		if (ptr_)
51 			ptr_ = mg_point_2d_copy(ptr_);
52 	}
53 
54 	@safe @nogc ~this() {
55 		if (ptr_)
56 			mg_point_2d_destroy(ptr_);
57 	}
58 
59 package:
60 	/// Create a Point2d using the given `mg_point_2d`.
61 	this(mg_point_2d *ptr) @trusted {
62 		assert(ptr != null);
63 		ptr_ = ptr;
64 	}
65 
66 	/// Create a Point2d from a copy of the given `mg_point_2d`.
67 	this(const mg_point_2d *ptr) {
68 		assert(ptr != null);
69 		this(mg_point_2d_copy(ptr));
70 	}
71 
72 	const (mg_point_2d *) ptr() const { return ptr_; }
73 
74 private:
75 	mg_point_2d *ptr_;
76 }
77 
78 unittest {
79 	import std.conv : to;
80 	import memgraph.enums;
81 
82 	auto tm = mg_point_2d_alloc(&mg_system_allocator);
83 	assert(tm != null);
84 	tm.srid = 42;
85 	tm.x = 6;
86 	tm.y = 7;
87 
88 	auto t = Point2d(tm);
89 	assert(t.srid == 42);
90 	assert(t.x == 6);
91 	assert(t.y == 7);
92 
93 	const t1 = t;
94 	assert(t1 == t);
95 
96 	assert(to!string(t) == "42 6 7");
97 
98 	auto t2 = Point2d(mg_point_2d_copy(t.ptr));
99 	assert(t2 == t);
100 
101 	const t3 = Point2d(t2);
102 	assert(t3 == t);
103 
104 	const v = Value(t);
105 	const t4 = Point2d(v);
106 	assert(t4 == t);
107 	assert(v == t);
108 	assert(to!string(v) == to!string(t));
109 
110 	t2 = t;
111 	assert(t2 == t);
112 
113 	const v1 = Value(t2);
114 	assert(v1.type == Type.Point2d);
115 	const v2 = Value(t2);
116 	assert(v2.type == Type.Point2d);
117 
118 	assert(v1 == v2);
119 
120 	const t5 = Point2d(t3);
121 	assert(t5 == t3);
122 }