Skip to content

Commit

Permalink
Port Segment2 to N-API
Browse files Browse the repository at this point in the history
Rework ToPod methods to be static; implement cascading parse/toPOD.
  • Loading branch information
fritzm committed Aug 8, 2019
1 parent 68466dc commit 3ea053a
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 93 deletions.
2 changes: 1 addition & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
# 'src/PolygonSet2.cc',
# 'src/PolygonWithHoles2.cc',
# 'src/Ray2.cc',
# 'src/Segment2.cc',
'src/Segment2.cc',
# 'src/Vector2.cc'
],

Expand Down
File renamed without changes.
11 changes: 5 additions & 6 deletions src/BBox2.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "BBox2.h"
#include "cgal_args.h"
#include "napi.h"

using namespace std;

Expand Down Expand Up @@ -52,13 +51,13 @@ bool BBox2::ParseArg(Napi::Env env, Napi::Value arg, Bbox_2& receiver)
}


Napi::Value BBox2::ToPOD(Napi::Env env, bool precise)
Napi::Value BBox2::ToPOD(Napi::Env env, Bbox_2 const& box, bool precise)
{
Napi::Object obj = Napi::Object::New(env);
obj.Set("xmin", mWrapped.xmin());
obj.Set("ymin", mWrapped.ymin());
obj.Set("xmax", mWrapped.xmax());
obj.Set("ymax", mWrapped.ymax());
obj.Set("xmin", box.xmin());
obj.Set("ymin", box.ymin());
obj.Set("xmax", box.xmax());
obj.Set("ymax", box.ymax());
return obj;
}

Expand Down
12 changes: 7 additions & 5 deletions src/BBox2.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "CGALWrapper.h"
#include "cgal_types.h"
#include "napi.h"

#include <vector>

Expand All @@ -15,17 +16,18 @@ class BBox2 : public CGALWrapper<BBox2, Bbox_2>
// The name to be used for our JS class.
static char const* Name;

// Convert our wrapped CGAL object to a POD JS object. If precise is set to false,
// attempt to render in terms of doubles for coordinates, which may lose precision.
// Add our property descriptors (instance and static methods and values) to the list that will
// be used to define our JS class. Called indirectly at module load time via the module
// init function.
static void AddProperties(std::vector<PropertyDescriptor>& properties);

// Attempt to parse a JS argument into the CGAL object referred to by receiver. Returns true
// if parse was successful, false otherwise.
static bool ParseArg(Napi::Env env, Napi::Value arg, Bbox_2& receiver);

// Convert our wrapped CGAL object to a POD JS object. If precise is set to false,
// attempt to render in terms of doubles for coordinates, which may lose precision.
Napi::Value ToPOD(Napi::Env env, bool precise);
// Convert a CGAL object of the wrapped class to a POD JS object. If precise is set to false,
// will attempt to render in terms of doubles for coordinates, and may lose precision.
static Napi::Value ToPOD(Napi::Env env, Bbox_2 const& box, bool precise);

private:

Expand Down
8 changes: 4 additions & 4 deletions src/CGALWrapper-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ Napi::Object CGALWrapper<WrapperClass, CGALClass>::New(Napi::Env env, const CGAL
}


template<typename NumberPrimitive>
bool ParseArg(Napi::Env env, Napi::Value arg, NumberPrimitive& parsed)
template<typename NumberType>
bool ParseNumberArg(Napi::Env env, Napi::Value arg, NumberType& parsed)
{
if (arg.IsNumber()) {
parsed = NumberPrimitive(arg.As<Napi::Number>());
parsed = arg.As<Napi::Number>();
return true;
} else if (arg.IsString()) {
std::istringstream str(arg.As<Napi::String>());
Expand Down Expand Up @@ -130,7 +130,7 @@ Napi::Value CGALWrapper<WrapperClass, CGALClass>::ToPOD(Napi::CallbackInfo const
precise = info[0].As<Napi::Boolean>();
}

return static_cast<WrapperClass*>(this)->ToPOD(env, precise);
return WrapperClass::ToPOD(env, mWrapped, precise);
}


Expand Down
4 changes: 2 additions & 2 deletions src/CGALWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ class CGALWrapper : public Napi::ObjectWrap<WrapperClass>

static Napi::Object New(Napi::Env env, const CGALClass &CGALInstance);

template<typename NumberPrimitive>
static bool ParseArg(Napi::Env env, Napi::Value arg, NumberPrimitive& parsed);
template<typename NumberType>
static bool ParseNumberArg(Napi::Env env, Napi::Value arg, NumberType& parsed);

template<typename OutputIterator>
static bool ParseSeqArg(Napi::Env env, Napi::Value arg, OutputIterator iterator);
Expand Down
18 changes: 9 additions & 9 deletions src/Point2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ bool Point2::ParseArg(Napi::Env env, Napi::Value arg, Point_2& receiver)
if (arg.IsArray()) {
Napi::Array coords = arg.As<Napi::Array>();
K::FT x, y;
if (::ParseArg(env, coords[0u], x) &&
::ParseArg(env, coords[1], y))
if (::ParseNumberArg(env, coords[0u], x) &&
::ParseNumberArg(env, coords[1], y))
{
receiver = Point_2(x, y);
return true;
Expand All @@ -48,27 +48,27 @@ bool Point2::ParseArg(Napi::Env env, Napi::Value arg, Point_2& receiver)
}


Napi::Value Point2::ToPOD(Napi::Env env, bool precise)
Napi::Value Point2::ToPOD(Napi::Env env, Point_2 const& point, bool precise)
{
Napi::Array array = Napi::Array::New(env, 2);
if (precise) {
ostringstream x_str;
#if CGAL_USE_EPECK
x_str << mWrapped.x().exact();
x_str << point.x().exact();
#else
x_str << setprecision(20) << mWrapped.x();
x_str << setprecision(20) << point.x();
#endif
array.Set(0u, x_str.str());
ostringstream y_str;
#if CGAL_USE_EPECK
y_str << mWrapped.y().exact();
y_str << point.y().exact();
#else
y_str << setprecision(20) << mWrapped.y();
y_str << setprecision(20) << point.y();
#endif
array.Set(1, y_str.str());
} else {
array.Set(0u, CGAL::to_double(mWrapped.cartesian(0)));
array.Set(1, CGAL::to_double(mWrapped.cartesian(1)));
array.Set(0u, CGAL::to_double(point.cartesian(0)));
array.Set(1, CGAL::to_double(point.cartesian(1)));
}

return array;
Expand Down
8 changes: 5 additions & 3 deletions src/Point2.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "cgal_types.h"
#include "napi.h"

#include <vector>

class Point2 : public CGALWrapper<Point2, Point_2>
{
public:
Expand All @@ -23,9 +25,9 @@ class Point2 : public CGALWrapper<Point2, Point_2>
// if parse was successful, false otherwise.
static bool ParseArg(Napi::Env env, Napi::Value arg, Point_2& receiver);

// Convert our wrapped CGAL object to a POD JS object. If precise is set to false,
// attempt to render in terms of doubles for coordinates, which may lose precision.
Napi::Value ToPOD(Napi::Env env, bool precise);
// Convert a CGAL object of the wrapped class to a POD JS object. If precise is set to false,
// will attempt to render in terms of doubles for coordinates, and may lose precision.
static Napi::Value ToPOD(Napi::Env env, Point_2 const& point, bool precise=true);

private:

Expand Down
78 changes: 30 additions & 48 deletions src/Segment2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,67 @@
#include "Point2.h"
#include "cgal_args.h"

using namespace v8;
using namespace node;

using namespace std;


Segment2::Segment2(Napi::CallbackInfo const& info)
: CGALWrapper(info)
{
}


const char *Segment2::Name = "Segment2";


void Segment2::RegisterMethods(Isolate *isolate)
void Segment2::AddProperties(vector<PropertyDescriptor>& properties)
{
HandleScope scope(isolate);
Local<FunctionTemplate> constructorTemplate = sConstructorTemplate.Get(isolate);
NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "isVertical", IsVertical);
NODE_SET_PROTOTYPE_METHOD(constructorTemplate, "isHorizontal", IsHorizontal);
properties.insert(properties.end(), {
InstanceMethod("isHorizontal", &Segment2::IsHorizontal),
InstanceMethod("isVertical", &Segment2::IsVertical)
});
}


bool Segment2::ParseArg(Isolate *isolate, Local<Value> arg, Segment_2 &receiver)
bool Segment2::ParseArg(Napi::Env env, Napi::Value arg, Segment_2& receiver)
{
HandleScope scope(isolate);
Local<Context> context = isolate->GetCurrentContext();

if (sConstructorTemplate.Get(isolate)->HasInstance(arg)) {
receiver = ExtractWrapped(Local<Object>::Cast(arg));
return true;
}
if (arg.IsObject()) {
Napi::Object obj = arg.As<Napi::Object>();

if (arg->IsObject()) {
Local<Object> ends = Local<Object>::Cast(arg);
if (obj.InstanceOf(sConstructor.Value())) {
receiver = Unwrap(obj)->mWrapped;
return true;
}

Point_2 source, target;

if (Point2::ParseArg(isolate, ends->Get(context, SYMBOL(isolate, "source")).ToLocalChecked(), source) &&
Point2::ParseArg(isolate, ends->Get(context, SYMBOL(isolate, "target")).ToLocalChecked(), target))
if (Point2::ParseArg(env, obj["source"], source) &&
Point2::ParseArg(env, obj["target"], target))
{
receiver = Segment_2(source, target);
return true;
}

}

return false;
}


Local<Value> Segment2::ToPOD(Isolate *isolate, const Segment_2 &segment, bool precise)
Napi::Value Segment2::ToPOD(Napi::Env env, Segment_2 const& segment, bool precise)
{
EscapableHandleScope scope(isolate);
Local<Context> context = isolate->GetCurrentContext();
Local<Object> obj = Object::New(isolate);
obj->Set(context, SYMBOL(isolate, "source"), Point2::ToPOD(isolate, segment.source(), precise));
obj->Set(context, SYMBOL(isolate, "target"), Point2::ToPOD(isolate, segment.target(), precise));
return scope.Escape(obj);
Napi::Object obj = Napi::Object::New(env);
obj.Set("source", Point2::ToPOD(env, segment.source(), precise));
obj.Set("target", Point2::ToPOD(env, segment.target(), precise));
return obj;
}


void Segment2::IsHorizontal(const FunctionCallbackInfo<Value> &info)
Napi::Value Segment2::IsHorizontal(Napi::CallbackInfo const& info)
{
Isolate *isolate = info.GetIsolate();
HandleScope scope(isolate);
try {
Segment_2 &segment = ExtractWrapped(info.This());
info.GetReturnValue().Set(Boolean::New(isolate, segment.is_horizontal()));
}
catch (const exception &e) {
isolate->ThrowException(String::NewFromUtf8(isolate, e.what(), NewStringType::kNormal).ToLocalChecked());
}
return Napi::Value::From(info.Env(), mWrapped.is_horizontal());
}


void Segment2::IsVertical(const FunctionCallbackInfo<Value> &info)
Napi::Value Segment2::IsVertical(Napi::CallbackInfo const& info)
{
Isolate *isolate = info.GetIsolate();
HandleScope scope(isolate);
try {
Segment_2 &segment = ExtractWrapped(info.This());
info.GetReturnValue().Set(Boolean::New(isolate, segment.is_vertical()));
}
catch (const exception &e) {
isolate->ThrowException(String::NewFromUtf8(isolate, e.what(), NewStringType::kNormal).ToLocalChecked());
}
return Napi::Value::From(info.Env(), mWrapped.is_vertical());
}
27 changes: 14 additions & 13 deletions src/Segment2.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,39 @@

#include "CGALWrapper.h"
#include "cgal_types.h"
#include "v8.h"

#include "napi.h"

class Segment2 : public CGALWrapper<Segment2, Segment_2>
{
public:

Segment2(Napi::CallbackInfo const& info);

// The name to be used for our JS class.
static const char *Name;

// Add our function templates to the package exports, and return string to be used to name
// the class and constructor in JS. Called indirectly at module load time via the module
// Add our property descriptors (instance and static methods and values) to the list that will
// be used to define our JS class. Called indirectly at module load time via the module
// init function.
static void RegisterMethods(v8::Isolate *isolate);
static void AddProperties(std::vector<PropertyDescriptor>& properties);

// Attempt to parse a v8 argument into the CGAL object referred to by receiver. Returns true
// Attempt to parse a JS argument into the CGAL object referred to by receiver. Returns true
// if parse was successful, false otherwise.
static bool ParseArg(v8::Isolate *isolate, v8::Local<v8::Value> arg, Segment_2 &receiver);
static bool ParseArg(Napi::Env env, Napi::Value arg, Segment_2& receiver);

// Convert a CGAL object of the wrapped class to a POD v8 object. If precise is set to false,
// will attempt to render in terms of doubles for coordinates, and may lose precision.
static v8::Local<v8::Value> ToPOD(v8::Isolate *isolate, const Segment_2 &segment, bool precise=true);
// Convert our wrapped CGAL object to a POD JS object. If precise is set to false,
// attempt to render in terms of doubles for coordinates, which may lose precision.
static Napi::Value ToPOD(Napi::Env env, Segment_2 const& segment, bool precise);

private:

//
//----- The following methods will be callable from JS. These will mostly match
//----- The following methods will be callable from JS. These will mostly match
// the semantics and names of the wrapped CGAL class.
//

static void IsHorizontal(const v8::FunctionCallbackInfo<v8::Value> &info);
static void IsVertical(const v8::FunctionCallbackInfo<v8::Value> &info);
Napi::Value IsHorizontal(Napi::CallbackInfo const& info);
Napi::Value IsVertical(Napi::CallbackInfo const& info);

};

Expand Down
4 changes: 2 additions & 2 deletions src/cgal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// #include "PolygonSet2.h"
// #include "PolygonWithHoles2.h"
// #include "Ray2.h"
// #include "Segment2.h"
#include "Segment2.h"
// #include "Vector2.h"

using namespace std;
Expand Down Expand Up @@ -61,7 +61,7 @@ Napi::Object Init(Napi::Env env, Napi::Object exports)
// PolygonSet2::Init(env, exports);
// PolygonWithHoles2::Init(env, exports);
// Ray2::Init(env, exports);
// Segment2::Init(env, exports);
Segment2::Init(env, exports);
// Vector2::Init(env, exports);

return exports;
Expand Down

0 comments on commit 3ea053a

Please sign in to comment.