mirror of https://github.com/KLayout/klayout.git
348 lines
11 KiB
C++
348 lines
11 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2024 Matthias Koefferlein
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef HDR_dbTriangles
|
|
#define HDR_dbTriangles
|
|
|
|
#include "dbCommon.h"
|
|
#include "dbTriangle.h"
|
|
#include "dbBox.h"
|
|
#include "dbRegion.h"
|
|
|
|
#include "tlObjectCollection.h"
|
|
#include "tlStableVector.h"
|
|
|
|
#include <limits>
|
|
#include <list>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
|
|
namespace db
|
|
{
|
|
|
|
class Layout;
|
|
|
|
class DB_PUBLIC Triangles
|
|
{
|
|
public:
|
|
struct TriangulateParameters
|
|
{
|
|
TriangulateParameters ()
|
|
: min_b (1.0),
|
|
min_length (0.0),
|
|
max_area (0.0),
|
|
max_area_border (0.0),
|
|
max_iterations (std::numeric_limits<size_t>::max ()),
|
|
base_verbosity (30),
|
|
mark_triangles (false)
|
|
{ }
|
|
|
|
/**
|
|
* @brief Min. readius-to-shortest edge ratio
|
|
*/
|
|
double min_b;
|
|
|
|
/**
|
|
* @brief Min. edge length
|
|
*
|
|
* This parameter does not provide a guarantee about a minimume edge length, but
|
|
* helps avoiding ever-reducing triangle splits in acute corners of the input polygon.
|
|
* Splitting of edges stops when the edge is less than the min length.
|
|
*/
|
|
double min_length;
|
|
|
|
/**
|
|
* @brief Max area or zero for "no constraint"
|
|
*/
|
|
double max_area;
|
|
|
|
/**
|
|
* @brief Max area for border triangles or zero for "use max_area"
|
|
*/
|
|
double max_area_border;
|
|
|
|
/**
|
|
* @brief Max number of iterations
|
|
*/
|
|
size_t max_iterations;
|
|
|
|
/**
|
|
* @brief The verbosity level above which triangulation reports details
|
|
*/
|
|
int base_verbosity;
|
|
|
|
/**
|
|
* @brief If true, final triangles are marked using the "id" integer as a bit field
|
|
*
|
|
* This provides information about the result quality.
|
|
*
|
|
* Bit 0: skinny triangle
|
|
* Bit 1: bad-quality (skinny or area too large)
|
|
* Bit 2: non-Delaunay (in the strict sense)
|
|
*/
|
|
bool mark_triangles;
|
|
};
|
|
|
|
typedef tl::list<db::Triangle> triangles_type;
|
|
typedef triangles_type::const_iterator triangle_iterator;
|
|
|
|
Triangles ();
|
|
~Triangles ();
|
|
|
|
/**
|
|
* @brief Initializes the triangle collection with a box
|
|
* Two triangles will be created.
|
|
*/
|
|
void init_box (const db::DBox &box);
|
|
|
|
/**
|
|
* @brief Returns a string representation of the triangle graph.
|
|
*/
|
|
std::string to_string ();
|
|
|
|
/**
|
|
* @brief Returns the bounding box of the triangle graph.
|
|
*/
|
|
db::DBox bbox () const;
|
|
|
|
/**
|
|
* @brief Iterates the triangles in the graph (begin iterator)
|
|
*/
|
|
triangle_iterator begin () const { return mp_triangles.begin (); }
|
|
|
|
/**
|
|
* @brief Iterates the triangles in the graph (end iterator)
|
|
*/
|
|
triangle_iterator end () const { return mp_triangles.end (); }
|
|
|
|
/**
|
|
* @brief Returns the number of triangles in the graph
|
|
*/
|
|
size_t num_triangles () const { return mp_triangles.size (); }
|
|
|
|
/**
|
|
* @brief Clears the triangle set
|
|
*/
|
|
void clear ();
|
|
|
|
/**
|
|
* @brief Creates a refined Delaunay triangulation for the given region
|
|
*
|
|
* The database unit should be chosen in a way that target area values are "in the order of 1".
|
|
* For inputs featuring acute angles (angles < ~25 degree), the parameters should defined a min
|
|
* edge length ("min_length").
|
|
* "min_length" should be at least 1e-4. If a min edge length is given, the max area constaints
|
|
* may not be satisfied.
|
|
*
|
|
* Edges in the input should not be shorter than 1e-4.
|
|
*/
|
|
void triangulate (const db::Region ®ion, const TriangulateParameters ¶meters, double dbu = 1.0);
|
|
|
|
// more versions
|
|
void triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, double dbu = 1.0);
|
|
void triangulate (const db::Region ®ion, const TriangulateParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ());
|
|
void triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ());
|
|
|
|
/**
|
|
* @brief Triangulates a floating-point polygon
|
|
*/
|
|
void triangulate (const db::DPolygon &poly, const TriangulateParameters ¶meters);
|
|
|
|
/**
|
|
* @brief Statistics: number of flips (fixing)
|
|
*/
|
|
size_t flips () const
|
|
{
|
|
return m_flips;
|
|
}
|
|
|
|
/**
|
|
* @brief Statistics: number of hops (searching)
|
|
*/
|
|
size_t hops () const
|
|
{
|
|
return m_hops;
|
|
}
|
|
|
|
protected:
|
|
/**
|
|
* @brief Checks the triangle graph for consistency
|
|
* This method is for testing purposes mainly.
|
|
*/
|
|
bool check (bool check_delaunay = true) const;
|
|
|
|
/**
|
|
* @brief Dumps the triangle graph to a GDS file at the given path
|
|
* This method is for testing purposes mainly.
|
|
*
|
|
* "decompose_id" will map triangles to layer 20, 21 and 22.
|
|
* according to bit 0, 1 and 2 of the ID (useful with the 'mark_triangles'
|
|
* flat in TriangulateParameters).
|
|
*/
|
|
void dump (const std::string &path, bool decompose_by_id = false) const;
|
|
|
|
/**
|
|
* @brief Creates a new layout object representing the triangle graph
|
|
* This method is for testing purposes mainly.
|
|
*/
|
|
db::Layout *to_layout (bool decompose_by_id = false) const;
|
|
|
|
/**
|
|
* @brief Finds the points within (not "on") a circle of radius "radius" around the given vertex.
|
|
*/
|
|
std::vector<db::Vertex *> find_points_around (Vertex *vertex, double radius);
|
|
|
|
/**
|
|
* @brief Inserts a new vertex as the given point
|
|
*
|
|
* If "new_triangles" is not null, it will receive the list of new triangles created during
|
|
* the remove step.
|
|
*/
|
|
db::Vertex *insert_point (const db::DPoint &point, std::list<tl::weak_ptr<db::Triangle> > *new_triangles = 0);
|
|
|
|
/**
|
|
* @brief Inserts a new vertex as the given point
|
|
*
|
|
* If "new_triangles" is not null, it will receive the list of new triangles created during
|
|
* the remove step.
|
|
*/
|
|
db::Vertex *insert_point (db::DCoord x, db::DCoord y, std::list<tl::weak_ptr<db::Triangle> > *new_triangles = 0);
|
|
|
|
/**
|
|
* @brief Removes the given vertex
|
|
*
|
|
* If "new_triangles" is not null, it will receive the list of new triangles created during
|
|
* the remove step.
|
|
*/
|
|
void remove (db::Vertex *vertex, std::list<tl::weak_ptr<db::Triangle> > *new_triangles = 0);
|
|
|
|
/**
|
|
* @brief Flips the given edge
|
|
*/
|
|
std::pair<std::pair<db::Triangle *, db::Triangle *>, db::TriangleEdge *> flip (TriangleEdge *edge);
|
|
|
|
/**
|
|
* @brief Finds all edges that cross the given one for a convex triangulation
|
|
*
|
|
* Requirements:
|
|
* * self must be a convex triangulation
|
|
* * edge must not contain another vertex from the triangulation except p1 and p2
|
|
*/
|
|
std::vector<db::TriangleEdge *> search_edges_crossing (db::Vertex *from, db::Vertex *to);
|
|
|
|
/**
|
|
* @brief Finds the edge for two given points
|
|
*/
|
|
db::TriangleEdge *find_edge_for_points (const db::DPoint &p1, const db::DPoint &p2);
|
|
|
|
/**
|
|
* @brief Finds the vertex for a point
|
|
*/
|
|
db::Vertex *find_vertex_for_point (const db::DPoint &pt);
|
|
|
|
/**
|
|
* @brief Ensures all points between from an to are connected by edges and makes these segments
|
|
*/
|
|
std::vector<db::TriangleEdge *> ensure_edge (db::Vertex *from, db::Vertex *to);
|
|
|
|
/**
|
|
* @brief Given a set of contours with edges, mark outer triangles
|
|
*
|
|
* The edges must be made from existing vertexes. Edge orientation is
|
|
* clockwise.
|
|
*
|
|
* This will also mark triangles as outside ones.
|
|
*/
|
|
void constrain (const std::vector<std::vector<Vertex *> > &contours);
|
|
|
|
/**
|
|
* @brief Removes the outside triangles.
|
|
*/
|
|
void remove_outside_triangles ();
|
|
|
|
/**
|
|
* @brief Creates a constrained Delaunay triangulation from the given Region
|
|
*/
|
|
void create_constrained_delaunay (const db::Region ®ion, const db::CplxTrans &trans = db::CplxTrans ());
|
|
|
|
/**
|
|
* @brief Creates a constrained Delaunay triangulation from the given Polygon
|
|
*/
|
|
void create_constrained_delaunay (const db::Polygon &poly, const db::CplxTrans &trans = db::CplxTrans ());
|
|
|
|
/**
|
|
* @brief Creates a constrained Delaunay triangulation from the given DPolygon
|
|
*/
|
|
void create_constrained_delaunay (const db::DPolygon &poly);
|
|
|
|
/**
|
|
* @brief Returns a value indicating whether the edge is "illegal" (violates the Delaunay criterion)
|
|
*/
|
|
static bool is_illegal_edge (db::TriangleEdge *edge);
|
|
|
|
// NOTE: these functions are SLOW and intended to test purposes only
|
|
std::vector<db::Vertex *> find_touching (const db::DBox &box) const;
|
|
std::vector<db::Vertex *> find_inside_circle (const db::DPoint ¢er, double radius) const;
|
|
|
|
private:
|
|
tl::list<db::Triangle> mp_triangles;
|
|
tl::stable_vector<db::TriangleEdge> m_edges_heap;
|
|
std::vector<db::TriangleEdge *> m_returned_edges;
|
|
tl::stable_vector<db::Vertex> m_vertex_heap;
|
|
bool m_is_constrained;
|
|
size_t m_level;
|
|
size_t m_id;
|
|
size_t m_flips, m_hops;
|
|
|
|
db::Vertex *create_vertex (double x, double y);
|
|
db::Vertex *create_vertex (const db::DPoint &pt);
|
|
db::TriangleEdge *create_edge (db::Vertex *v1, db::Vertex *v2);
|
|
db::Triangle *create_triangle (db::TriangleEdge *e1, db::TriangleEdge *e2, db::TriangleEdge *e3);
|
|
void remove_triangle (db::Triangle *tri);
|
|
|
|
void remove_outside_vertex (db::Vertex *vertex, std::list<tl::weak_ptr<db::Triangle> > *new_triangles = 0);
|
|
void remove_inside_vertex (db::Vertex *vertex, std::list<tl::weak_ptr<db::Triangle> > *new_triangles_out = 0);
|
|
std::vector<db::Triangle *> fill_concave_corners (const std::vector<TriangleEdge *> &edges);
|
|
void fix_triangles (const std::vector<db::Triangle *> &tris, const std::vector<db::TriangleEdge *> &fixed_edges, std::list<tl::weak_ptr<db::Triangle> > *new_triangles);
|
|
std::vector<db::Triangle *> find_triangle_for_point (const db::DPoint &point);
|
|
db::TriangleEdge *find_closest_edge (const db::DPoint &p, db::Vertex *vstart = 0, bool inside_only = false);
|
|
db::Vertex *insert (db::Vertex *vertex, std::list<tl::weak_ptr<db::Triangle> > *new_triangles = 0);
|
|
void split_triangle (db::Triangle *t, db::Vertex *vertex, std::list<tl::weak_ptr<db::Triangle> > *new_triangles_out);
|
|
void split_triangles_on_edge (const std::vector<db::Triangle *> &tris, db::Vertex *vertex, db::TriangleEdge *split_edge, std::list<tl::weak_ptr<db::Triangle> > *new_triangles_out);
|
|
void add_more_triangles (std::vector<Triangle *> &new_triangles,
|
|
db::TriangleEdge *incoming_edge,
|
|
db::Vertex *from_vertex, db::Vertex *to_vertex,
|
|
db::TriangleEdge *conn_edge);
|
|
void insert_new_vertex(db::Vertex *vertex, std::list<tl::weak_ptr<Triangle> > *new_triangles_out);
|
|
std::vector<db::TriangleEdge *> ensure_edge_inner (db::Vertex *from, db::Vertex *to);
|
|
void join_edges (std::vector<TriangleEdge *> &edges);
|
|
void refine (const TriangulateParameters ¶m);
|
|
template<class Poly, class Trans> void make_contours (const Poly &poly, const Trans &trans, std::vector<std::vector<db::Vertex *> > &contours);
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|