#include "../gdal_common.hpp"
#include "../gdal_geometry.hpp"
#include "../gdal_linestring.hpp"
#include "../gdal_point.hpp"
#include "linestring_points.hpp"
namespace node_gdal {
Nan::Persistent<FunctionTemplate> LineStringPoints::constructor;
void LineStringPoints::Initialize(Local<Object> target)
{
Nan::HandleScope scope;
Local<FunctionTemplate> lcons = Nan::New<FunctionTemplate>(LineStringPoints::New);
lcons->InstanceTemplate()->SetInternalFieldCount(1);
lcons->SetClassName(Nan::New("LineStringPoints").ToLocalChecked());
Nan::SetPrototypeMethod(lcons, "toString", toString);
Nan::SetPrototypeMethod(lcons, "count", count);
Nan::SetPrototypeMethod(lcons, "get", get);
Nan::SetPrototypeMethod(lcons, "set", set);
Nan::SetPrototypeMethod(lcons, "add", add);
Nan::SetPrototypeMethod(lcons, "reverse", reverse);
Nan::SetPrototypeMethod(lcons, "resize", resize);
Nan::Set(target, Nan::New("LineStringPoints").ToLocalChecked(), Nan::GetFunction(lcons).ToLocalChecked());
constructor.Reset(lcons);
}
LineStringPoints::LineStringPoints()
: Nan::ObjectWrap()
{}
LineStringPoints::~LineStringPoints()
{}
/**
* An encapsulation of a {{#crossLink "gdal.LineString"}}LineString{{/crossLink}}'s points.
*
* @class gdal.LineStringPoints
*/
NAN_METHOD(LineStringPoints::New)
{
Nan::HandleScope scope;
if (!info.IsConstructCall()) {
Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword");
return;
}
if (info[0]->IsExternal()) {
Local<External> ext = info[0].As<External>();
void* ptr = ext->Value();
LineStringPoints *geom = static_cast<LineStringPoints *>(ptr);
geom->Wrap(info.This());
info.GetReturnValue().Set(info.This());
return;
} else {
Nan::ThrowError("Cannot create LineStringPoints directly");
return;
}
}
Local<Value> LineStringPoints::New(Local<Value> geom)
{
Nan::EscapableHandleScope scope;
LineStringPoints *wrapped = new LineStringPoints();
v8::Local<v8::Value> ext = Nan::New<External>(wrapped);
v8::Local<v8::Object> obj = Nan::NewInstance(Nan::GetFunction(Nan::New(LineStringPoints::constructor)).ToLocalChecked(), 1, &ext).ToLocalChecked();
Nan::SetPrivate(obj, Nan::New("parent_").ToLocalChecked(), geom);
return scope.Escape(obj);
}
NAN_METHOD(LineStringPoints::toString)
{
Nan::HandleScope scope;
info.GetReturnValue().Set(Nan::New("LineStringPoints").ToLocalChecked());
}
/**
* Returns the number of points that are part of the line string.
*
* @method count
* @return {Integer}
*/
NAN_METHOD(LineStringPoints::count)
{
Nan::HandleScope scope;
Local<Object> parent = Nan::GetPrivate(info.This(), Nan::New("parent_").ToLocalChecked()).ToLocalChecked().As<Object>();
LineString *geom = Nan::ObjectWrap::Unwrap<LineString>(parent);
info.GetReturnValue().Set(Nan::New<Integer>(geom->get()->getNumPoints()));
}
/**
* Reverses the order of all the points.
*
* @method reverse
*/
NAN_METHOD(LineStringPoints::reverse)
{
Nan::HandleScope scope;
Local<Object> parent = Nan::GetPrivate(info.This(), Nan::New("parent_").ToLocalChecked()).ToLocalChecked().As<Object>();
LineString *geom = Nan::ObjectWrap::Unwrap<LineString>(parent);
geom->get()->reversePoints();
return;
}
/**
* Adjusts the number of points that make up the line string.
*
* @method resize
* @param {Integer} count
*/
NAN_METHOD(LineStringPoints::resize)
{
Nan::HandleScope scope;
Local<Object> parent = Nan::GetPrivate(info.This(), Nan::New("parent_").ToLocalChecked()).ToLocalChecked().As<Object>();
LineString *geom = Nan::ObjectWrap::Unwrap<LineString>(parent);
int count;
NODE_ARG_INT(0, "point count", count)
geom->get()->setNumPoints(count);
return;
}
/**
* Returns the point at the specified index.
*
* @method get
* @param {Integer} index 0-based index
* @return {gdal.Point}
*/
NAN_METHOD(LineStringPoints::get)
{
Nan::HandleScope scope;
Local<Object> parent = Nan::GetPrivate(info.This(), Nan::New("parent_").ToLocalChecked()).ToLocalChecked().As<Object>();
LineString *geom = Nan::ObjectWrap::Unwrap<LineString>(parent);
OGRPoint *pt = new OGRPoint();
int i;
NODE_ARG_INT(0, "index", i);
if(i < 0 || i >= geom->get()->getNumPoints()) {
info.GetReturnValue().Set(Nan::Null());
return;
}
geom->get()->getPoint(i, pt);
info.GetReturnValue().Set(Point::New(pt));
}
/**
* Sets the point at the specified index.
*
* @example
* ```
* lineString.points.set(0, new gdal.Point(1, 2));```
*
* @method set
* @throws Error
* @param {Integer} index 0-based index
* @param {gdal.Point} point
*/
NAN_METHOD(LineStringPoints::set)
{
Nan::HandleScope scope;
Local<Object> parent = Nan::GetPrivate(info.This(), Nan::New("parent_").ToLocalChecked()).ToLocalChecked().As<Object>();
LineString *geom = Nan::ObjectWrap::Unwrap<LineString>(parent);
int i;
NODE_ARG_INT(0, "index", i);
if(i < 0 || i >= geom->get()->getNumPoints()) {
Nan::ThrowError("Point index out of range");
return;
}
int n = info.Length() - 1;
if(n == 0) {
Nan::ThrowError("Point must be given");
return;
} else if(n == 1) {
if(!info[1]->IsObject()) {
Nan::ThrowError("Point or object expected for second argument");
return;
}
if(IS_WRAPPED(info[1], Point)){
//set from Point object
Point* pt = Nan::ObjectWrap::Unwrap<Point>(info[1].As<Object>());
geom->get()->setPoint(i, pt->get());
} else {
Local<Object> obj = info[1].As<Object>();
//set from object {x: 0, y: 5}
double x, y;
NODE_DOUBLE_FROM_OBJ(obj, "x", x);
NODE_DOUBLE_FROM_OBJ(obj, "y", y);
Local<String> z_prop_name = Nan::New("z").ToLocalChecked();
if (Nan::HasOwnProperty(obj, z_prop_name).FromMaybe(false)) {
Local<Value> z_val = Nan::Get(obj, z_prop_name).ToLocalChecked();
if (!z_val->IsNumber()) {
Nan::ThrowError("z property must be number");
return;
}
geom->get()->setPoint(i, x, y, Nan::To<double>(z_val).ToChecked());
} else {
geom->get()->setPoint(i, x, y);
}
}
} else {
//set x, y, z from numeric arguments
if(!info[1]->IsNumber()){
Nan::ThrowError("Number expected for second argument");
return;
}
if(!info[2]->IsNumber()){
Nan::ThrowError("Number expected for third argument");
return;
}
if(n == 2){
geom->get()->setPoint(i, Nan::To<double>(info[1]).ToChecked(), Nan::To<double>(info[2]).ToChecked());
} else {
if(!info[3]->IsNumber()){
Nan::ThrowError("Number expected for fourth argument");
return;
}
geom->get()->setPoint(i, Nan::To<double>(info[1]).ToChecked(), Nan::To<double>(info[2]).ToChecked(), Nan::To<double>(info[3]).ToChecked());
}
}
return;
}
/**
* Adds point(s) to the line string. Also accepts any object with an x and y property.
*
* @example
* ```
* lineString.points.add(new gdal.Point(1, 2));
* lineString.points.add([
* new gdal.Point(1, 2)
* new gdal.Point(3, 4)
* ]);```
*
* @method add
* @throws Error
* @param {gdal.Point|object|Array} point(s)
*/
NAN_METHOD(LineStringPoints::add)
{
Nan::HandleScope scope;
Local<Object> parent = Nan::GetPrivate(info.This(), Nan::New("parent_").ToLocalChecked()).ToLocalChecked().As<Object>();
LineString *geom = Nan::ObjectWrap::Unwrap<LineString>(parent);
int n = info.Length();
if(n == 0) {
Nan::ThrowError("Point must be given");
return;
} else if(n == 1) {
if(!info[0]->IsObject()) {
Nan::ThrowError("Point, object, or array of points expected");
return;
}
if(IS_WRAPPED(info[0], Point)){
//set from Point object
Point* pt = Nan::ObjectWrap::Unwrap<Point>(info[0].As<Object>());
geom->get()->addPoint(pt->get());
} else if (info[0]->IsArray()) {
//set from array of points
Local<Array> array = info[0].As<Array>();
int length = array->Length();
for (int i = 0; i < length; i++){
Local<Value> element = Nan::Get(array, i).ToLocalChecked();
if(!element->IsObject()) {
Nan::ThrowError("All points must be Point objects or objects");
return;
}
Local<Object> element_obj = element.As<Object>();
if(IS_WRAPPED(element_obj, Point)){
//set from Point object
Point* pt = Nan::ObjectWrap::Unwrap<Point>(element_obj);
geom->get()->addPoint(pt->get());
} else {
//set from object {x: 0, y: 5}
double x, y;
NODE_DOUBLE_FROM_OBJ(element_obj, "x", x);
NODE_DOUBLE_FROM_OBJ(element_obj, "y", y);
Local<String> z_prop_name = Nan::New("z").ToLocalChecked();
if (Nan::HasOwnProperty(element_obj, z_prop_name).FromMaybe(false)) {
Local<Value> z_val = Nan::Get(element_obj, z_prop_name).ToLocalChecked();
if (!z_val->IsNumber()) {
Nan::ThrowError("z property must be number");
return;
}
geom->get()->addPoint(x, y, Nan::To<double>(z_val).ToChecked());
} else {
geom->get()->addPoint(x, y);
}
}
}
} else {
//set from object {x: 0, y: 5}
Local<Object> obj = info[0].As<Object>();
double x, y;
NODE_DOUBLE_FROM_OBJ(obj, "x", x);
NODE_DOUBLE_FROM_OBJ(obj, "y", y);
Local<String> z_prop_name = Nan::New("z").ToLocalChecked();
if (Nan::HasOwnProperty(obj, z_prop_name).FromMaybe(false)) {
Local<Value> z_val = Nan::Get(obj, z_prop_name).ToLocalChecked();
if (!z_val->IsNumber()) {
Nan::ThrowError("z property must be number");
return;
}
geom->get()->addPoint(x, y, Nan::To<double>(z_val).ToChecked());
} else {
geom->get()->addPoint(x, y);
}
}
} else {
//set x, y, z from numeric arguments
if(!info[0]->IsNumber()){
Nan::ThrowError("Number expected for first argument");
return;
}
if(!info[1]->IsNumber()){
Nan::ThrowError("Number expected for second argument");
return;
}
if(n == 2){
geom->get()->addPoint(Nan::To<double>(info[0]).ToChecked(), Nan::To<double>(info[1]).ToChecked());
} else {
if(!info[2]->IsNumber()){
Nan::ThrowError("Number expected for third argument");
return;
}
geom->get()->addPoint(Nan::To<double>(info[0]).ToChecked(), Nan::To<double>(info[1]).ToChecked(), Nan::To<double>(info[2]).ToChecked());
}
}
return;
}
} // namespace node_gdal