Commit 7acb9b2f authored by Jason Pries's avatar Jason Pries Committed by GitHub
Browse files

Refactor after move to CMake/GoogleTest (#1)

* Translate tests from CMake to GoogleTest
* Split Branch/Star/Constellation into multiple files
* Update Sketch.save_as to create directory if it does not exist using Boost::Filesystem
* Split Constraint.h/Constraint.cpp into multiple h/cpp files
* Split Pattern.h/Pattern.cpp into multiple h/cpp files
* Separate mesh/Point class in to own Point.h/Point.cpp files
* Separate mesh/utility functions into own util.h/util.cpp files
* Fixed problem with Sketch Contour/Boundary parsing related to supremum calculations
* Added .oesk extension for sketch output files
* Added .oeme extension for mesh output files
* Add build_gallery.py python script. Parses ./build/test/output directory for .oesk and .oeme files and saves images using matplotlib
* Removed using namespace std
* Updated implementation of RotateCopy
* Added RemoveInternalBoundary option to Pattern and subclasses
* Rewrote Mesh::locate_triangle function
* Changed type of Mesh.Points from vector<Point*> to vector<Point>
* Changed Edge members from type Edge* to type size_t
* Cleanup of Edge and Node access interface in Mesh
* Change Mesh::Edges from type std::vector<Edge*> to std::Vector<Edge>
* Add std::vector<DartConstraint> Constraints to Mesh. Revamp of constraint handling.
* Change Sketch Variable and Vertex vectors from raw pointers to shared pointers
* Change Sketch Boundary and Contour vector from raw pointers to shared pointers
* Change Sketch Pattern vector from raw pointers to shared pointers
* Change Sketch Constraint and Curve vectors from raw pointers to shared pointers
* Fix memory leaks
* Cleanup of Sketch and reorganization of dependencies
* Add shared_ptr const correctness to Sketch
* Robustified implementation of Sketch::solve()
* Started refactorization of mesh refinement control algorithm
parent 8a5e489b
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/lib/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/lib/GoogleTest/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/lib/GoogleTest/googletest/src/gtest_main.cc" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/lib/GoogleTest/googletest/src/gtest-all.cc" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/lib/GoogleTest/googletest/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/lib/GoogleTest/googletest/cmake/internal_utils.cmake" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Curve.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Pattern.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/CircularArc.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Contour.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Curve.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constraint.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/CircularArc.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertex.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Sketch.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constellation.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Pattern.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/LineSegment.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Vertex.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constellation.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/LineSegment.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Contour.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Sketch.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/src/Constraint.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/include/Sketch.hpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/Sketch/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/main.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/CMakeLists.txt" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/Sketch/test_Sketch.h" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/Sketch/test_LineSegment.cpp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/Sketch/test_Vertex.cpp" isTestSource="false" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library name="Header Search Paths">
<CLASSES>
<root url="file:///usr/include" />
<root url="file:///usr/lib/gcc/x86_64-redhat-linux/6.2.1/include" />
<root url="file:///usr/local/include" />
</CLASSES>
<SOURCES>
<root url="file:///usr/include" />
<root url="file:///usr/lib/gcc/x86_64-redhat-linux/6.2.1/include" />
<root url="file:///usr/local/include" />
</SOURCES>
</library>
</orderEntry>
</component>
</module>
\ No newline at end of file
<module classpath="CMake" type="CPP_MODULE" version="4" />
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" />
<pair source="c" header="h" />
</extensions>
</Objective-C-extensions>
</value>
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
</component>
</project>
\ No newline at end of file
......@@ -2,6 +2,7 @@
<dictionary name="jpries">
<words>
<w>eigen</w>
<w>supremum</w>
<w>tangency</w>
<w>verticies</w>
</words>
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
<component name="CidrRootsConfiguration">
<excludeRoots>
<file path="$PROJECT_DIR$/cmake-build-debug/CMakeFiles" />
<file path="$PROJECT_DIR$/cmake-build-minsizerel/CMakeFiles" />
<file path="$PROJECT_DIR$/cmake-build-release/CMakeFiles" />
</excludeRoots>
</component>
</project>
\ No newline at end of file
......@@ -10,12 +10,13 @@ matrix:
apt:
sources:
- ubuntu-toolchain-r-test
- boost-latest
- george-edison55-precise-backports
packages:
- cmake
- cmake-data
- g++-6
#- lcov
- libboost1.55-all-dev
before_install:
- mkdir -p $HOME/bin
......
......@@ -2,13 +2,23 @@ cmake_minimum_required(VERSION 3.2)
project(Oersted)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
find_package(Boost REQUIRED COMPONENTS system filesystem)
include_directories(${Boost_INCLUDE_DIR})
include_directories(./lib/)
include_directories(./lib/Eigen/)
include_directories(./lib/GoogleTest/googletest/include/gtest)
include_directories(./lib/ ./lib/Eigen/ ./lib/GoogleTest/googletest/include/gtest)
add_subdirectory(./lib/)
include_directories(./src/ ./src/Sketch/include)
include_directories(./src/)
include_directories(./src/Sketch/include/)
include_directories(./src/Mesh/include/)
add_subdirectory(./src/)
add_subdirectory(./test/)
add_subdirectory(./test/)
\ No newline at end of file
# ØRSTED :: Oak Ridge Simulation Toolkit for Electromechanical Devices
[![Build Status](https://travis-ci.org/JasonPries/Oersted.svg?branch=master)](https://travis-ci.org/JasonPries/Oersted)
[![Coverage Status](https://coveralls.io/repos/github/JasonPries/Oersted/badge.svg?branch=master)](https://coveralls.io/github/JasonPries/Oersted?branch=master)
[![Build Status](https://travis-ci.org/JasonPries/Oersted.svg?branch=vs2cmake)](https://travis-ci.org/JasonPries/Oersted)
[![Coverage Status](https://coveralls.io/repos/github/JasonPries/Oersted/badge.svg?branch=vs2cmake)](https://coveralls.io/github/JasonPries/Oersted?branch=vs2cmake)
\ No newline at end of file
......@@ -10,8 +10,9 @@ mkdir -p coverage
COV_FILE="coverage/coverage.info"
COV_DIR=".coverage"
COV_SITE=$COV_DIR/"index.html"
RM_PREFIX="${PWD%/*}/src"
lcov -c -d .. -o $COV_FILE
lcov -r $COV_FILE "*Oersted/lib/*" "*Oersted/test/*" "/usr/include/*" "/usr/lib/*" -o $COV_FILE
genhtml $COV_FILE -o $COV_DIR
genhtml $COV_FILE -o $COV_DIR -p $RM_PREFIX
google-chrome $COV_SITE
import os
import numpy as np
import matplotlib.pyplot as plt
imgtypes = ['.pdf','.png']
def plot_sketch(fname):
print('Sketch: ' +fname)
data = np.genfromtxt(fname, dtype=float, delimiter=',')
plt.plot(data[:,0], data[:,1])
plt.grid(True)
plt.axes().set_aspect('equal','datalim')
for ext in imgtypes:
plt.savefig(fname+ext)
plt.clf()
def plot_mesh(fname):
print('Mesh: '+fname)
data = np.genfromtxt(fname, dtype=float, delimiter=',')
x = data[:,[0,1,2,0]].transpose()
y = data[:,[3,4,5,3]].transpose()
plt.plot(x,y,'b')
plt.grid(True)
plt.axes().set_aspect('equal','datalim')
for ext in imgtypes:
plt.savefig(fname+ext)
plt.clf()
root = os.getcwd()
root += '/build/test/output/'
for path, _, files in os.walk(root):
for name in files:
_, fext = os.path.splitext(name)
fpath = os.path.join(path, name)
if fext == '.oesk':
plot_sketch(fpath)
elif fext == '.oeme':
plot_mesh(fpath)
\ No newline at end of file
include_directories(./Sketch/)
include_directories(./Mesh/)
add_subdirectory(./Sketch/)
add_subdirectory(./Mesh/)
\ No newline at end of file
PROJECT(Oersted_Mesh)
set(SOURCE_FILES
./include/Mesh.hpp
./src/Mesh.h ./src/Mesh.cpp
./src/Edge.h ./src/Edge.cpp
./src/Point.h ./src/Point.cpp)
add_library(mesh STATIC ${SOURCE_FILES})
target_link_libraries(mesh ${Boost_LIBRARIES})
\ No newline at end of file
#ifndef OERSTED_MESH_HPP
#define OERSTED_MESH_HPP
#include <boost/filesystem.hpp>
#include "../src/Mesh.h"
#include "../src/Edge.h"
#include "../src/Point.h"
#endif //OERSTED_MESH_HPP
\ No newline at end of file
#include "Mesh.hpp"
\ No newline at end of file
#ifndef OERSTED_EDGE_H
#define OERSTED_EDGE_H
#include "Point.h"
class Mesh;
class Edge {
public:
friend class Mesh;
Edge() : Node(SIZE_MAX), Self(SIZE_MAX), Next(SIZE_MAX), Twin(SIZE_MAX), Prev(SIZE_MAX), Constraint(SIZE_MAX), Orientation(true), Mark(false) {};
Edge(size_t s) : Node(SIZE_MAX), Self(s), Next(SIZE_MAX), Twin(SIZE_MAX), Prev(SIZE_MAX), Constraint(SIZE_MAX), Orientation(true), Mark(false) {};
Edge(size_t n, size_t s, Edge &nx, Edge &pr, Edge &tw) : Node(n), Self(s), Next(nx.Self), Twin(tw.Self), Prev(pr.Self), Constraint(SIZE_MAX), Orientation(true), Mark(false) {};
Edge(size_t n, size_t s, size_t c, bool d) : Node(n), Self(s), Next(SIZE_MAX), Twin(SIZE_MAX), Prev(SIZE_MAX), Constraint(c), Orientation(d), Mark(false) {};
size_t node() const { return Node; };
size_t self() const { return Self; };
size_t next() const { return Next; };
size_t twin() const { return Twin; };
size_t prev() const { return Prev; };
bool orientation() const { return Orientation; };
bool mark() const { return Mark; };
bool operator==(Edge const &e) const {
return (Node == e.Node &&
Self == e.Self &&
Next == e.Next &&
Twin == e.Twin &&
Prev == e.Prev &&
Constraint == e.Constraint &&
Orientation == e.Orientation);
};
protected:
size_t Node; //Point at start of this edge
size_t Self; //This edge in this triangle
size_t Next; //Next edge in this triangle
size_t Twin; //Twin edge in adjacent triangle
size_t Prev; //Previous edge in this triangle
size_t Constraint; //DartConstraint index
bool Orientation; //don't care if unconstrained
bool Mark; //Auxiliary variable for mesh refinement
};
#endif //OERSTED_EDGE_H
#include "Mesh.hpp"
Mesh::Mesh(Sketch &sketch) {
Boundary = sketch.boundary();
for (size_t i = 0; i != sketch.size_curves(); ++i) {
auto c = sketch.curve(i);
if (!(c->for_construction())) {
Curves.push_back(c);
}
}
for (size_t i = 0; i != sketch.size_contours(); ++i) {
Contours.push_back(sketch.contour(i));
}
Constraints.push_back(DartConstraint());
}
bool Mesh::are_intersecting(size_t ei, size_t ej) const {
// TODO, Make more detailed return type enumeration
if (is_constrained(ei) && constraint_curve(ei) == constraint_curve(ej)) {
return false;
}
Point const v00 = base(ei);
Point const v01 = tip(ei);
Point const v10 = base(ej);
Point const v11 = tip(ej);
double xs0 = (v00.X + v01.X) / 2.0;
double ys0 = (v00.Y + v01.Y) / 2.0;
double xs1 = (v10.X + v11.X) / 2.0;
double ys1 = (v10.Y + v11.Y) / 2.0;
double xd0 = (v00.X - v01.X) / 2.0;
double yd0 = (v00.Y - v01.Y) / 2.0;
double xd1 = (v10.X - v11.X) / 2.0;
double yd1 = (v10.Y - v11.Y) / 2.0;
double d0 = xd0 * xd0 + yd0 * yd0;
double d1 = xd1 * xd1 + yd1 * yd1;
double cross = abs(xd0 * yd1 - xd1 * yd0);
double tol = (d0 * d1) * FLT_EPSILON;
if (cross < tol) {
// Lines are nearly parallel
// There are four possible minimum distance points between the lines
double s, dx, dy, dmin = DBL_MAX;
s = ((xd0 - xd1) * (xs0 - xs1) + (yd0 - yd1) * (ys0 - ys1)) /
((xd0 - xd1) * (xd0 - xd1) + (yd0 - yd1) * (yd0 - yd1));
if (abs(s) < 1.0 - FLT_EPSILON) {
dx = xs0 + xd0 * s - xs1 - xd1 * s;
dy = ys0 + yd0 * s - ys1 - yd1 * s;
dmin = std::fmin(dmin, dx * dx + dy * dy);
dx = xs0 - xd0 * s - xs1 + xd1 * s;
dy = ys0 - yd0 * s - ys1 + yd1 * s;
dmin = std::fmin(dmin, dx * dx + dy * dy);
}
s = ((xd0 + xd1) * (xs0 - xs1) + (yd0 + yd1) * (ys0 - ys1)) /
((xd0 + xd1) * (xd0 + xd1) + (yd0 + yd1) * (yd0 + yd1));
if (abs(s) < 1.0 - FLT_EPSILON) {
dx = xs0 + xd0 * s - xs1 + xd1 * s;
dy = ys0 + yd0 * s - ys1 + yd1 * s;
dmin = std::fmin(dmin, dx * dx + dy * dy);
dx = xs0 - xd0 * s - xs1 - xd1 * s;
dy = ys0 - yd0 * s - ys1 - yd1 * s;
dmin = std::fmin(dmin, dx * dx + dy * dy);
}
tol = (d0 + d1) * FLT_EPSILON;
return (dmin < tol);
} else { // Lines are not parallel
double s0 = abs(xd1 * (ys0 - ys1) - yd1 * (xs0 - xs1));
double s1 = abs(xd0 * (ys0 - ys1) - yd0 * (xs0 - xs1));
tol = cross * (1.0 - FLT_EPSILON);
return (s0 < tol && s1 < tol);
}
}
bool Mesh::edges_are_valid() const {
bool result = true;
for (size_t e = 0; e != Edges.size(); ++e) {
if (e != prev(next(e))) {
result = false;
break;
}
if (e != next(prev(e))) {
result = false;
break;
}
if (e != twin(twin(e))) {
result = false;
break;
}
if ((e != twin(e))) {
if (node(e) != node(next(twin(e)))) {
result = false;
break;
}
if (constraint_curve(e) != constraint_curve(twin(e))) {
result = false;
break;
}
if (is_constrained(e)) {
if (orientation(e) == orientation(twin(e))) {
result = false;
break;
}
}
if (node(e) == node(twin(e))) {
result = false;
break;
}
}
if (is_constrained(e)) {
DartConstraint dc = Constraints[Edges[e].Constraint];
double tol = length(e) * FLT_EPSILON;
if (orientation(e)) {
Point p0 = base(e);
Point p1 = dc.ConstraintCurve->point(dc.S0);
if (dist(p0,p1) > tol) {
result = false;
break;
}
p0 = tip(e);
p1 = dc.ConstraintCurve->point(dc.S1);
if (dist(p0,p1) > tol) {
result = false;
break;
}
} else {
Point p0 = base(e);
Point p1 = dc.ConstraintCurve->point(dc.S1);
if (dist(p0,p1) > tol) {
result = false;
break;
}
p0 = tip(e);
p1 = dc.ConstraintCurve->point(dc.S0);
if (dist(p0,p1) > tol) {
result = false;
break;
}
}
}
}
return result;
}
bool Mesh::find_attached(Point const p, size_t &e_out) {
double tol = length(e_out) * FLT_EPSILON;
if (dist(tip(e_out),p) < tol) {
return true;
}
size_t e_in = e_out;
if (e_out != twin(e_out)) {
e_out = next(twin(e_out));
while (e_out != e_in) {
if (dist(tip(e_out),p) < tol) {
return true;
} else if (e_out != twin(e_out)) {
e_out = next(twin(e_out));
} else {
break;
}
}
}
if (e_out == twin(e_out)) {
e_out = prev(e_in);
while (e_out != twin(e_out)) {
if (dist(base(e_out),p) < tol) {
e_out = twin(e_out);
return true;
} else {
e_out = prev(twin(e_out));
}
}
}
return false;
}
bool Mesh::refine() {
std::vector<double> radii;
std::vector<double> quality;
std::vector<size_t> index;
// TODO: Loop until quality is satisfied
// TODO: Iteratively decrease the min and max element size until quality is satisfied
// TODO: plan() bounds on maximum element quality
// TODO: First: refine until maximum element size criteria is satisfied
// TODO: plan() out iterative maximum element size refinement
// TODO: Then: refine until element quality cirteria is satisfied
// TODO: ?somehow iterate?
// TODO: SMOOTHING!
element_quality(radii, quality);
//sort_permutation_ascending(quality, index);
sort_permutation_descending(radii, index);
size_t N = Triangles.size();
refine_once(index, radii, quality);
size_t M = Triangles.size();
while (M > N) {
N = M;
element_quality(radii, quality);
//sort_permutation_ascending(quality, index);
sort_permutation_descending(radii, index);
refine_once(index, radii, quality);
M = Triangles.size();
}
return edges_are_valid(); // TODO: Instrument in tests
}
bool Mesh::refine_once() {
std::vector<double> radii;
std::vector<double> quality;
std::vector<size_t> index;
element_quality(radii, quality);
//sort_permutation_ascending(quality, index);
sort_permutation_descending(radii, index);
refine_once(index, radii, quality);
return edges_are_valid(); // TODO: Instrument in tests
}
bool Mesh::in_triangle(Point const p, size_t ei) const {
double xp = p.X;
double yp = p.Y;
Point const p0 = base(ei);
Point const p1 = base(next(ei));
Point const p2 = base(prev(ei));
double dx0p = p0.X - xp;
double dy0p = p0.Y - yp;
double dx1p = p1.X - xp;
double dy1p = p1.Y - yp;
double dx2p = p2.X - xp;
double dy2p = p2.Y - yp;
double dx01 = p0.X - p1.X;
double dy01 = p0.Y - p1.Y;
double dx12 = p1.X - p2.X;
double dy12 = p1.Y - p2.Y;
double dx20 = p2.X - p0.X;
double dy20 = p2.Y - p0.Y;
double area012 = dx01 * dy12 - dy01 * dx12;
double tol = FLT_EPSILON * area012;
double area01p = dx0p * dy1p - dx1p * dy0p;
double area12p = dx1p * dy2p - dx2p * dy1p;
double area20p = dx2p * dy0p - dx0p * dy2p;
return (area01p > -tol && area12p > -tol && area20p > -tol);
}
bool Mesh::is_encroached(Point const p, size_t ei) const {
/*