/** * PANDA 3D SOFTWARE * Copyright (c) Carnegie Mellon University. All rights reserved. * * All use of this software is subject to the terms of the revised BSD * license. You should have received a copy of this license along * with this source code in a file named "LICENSE." * * @file triangulator.h * @author drose * @date 2007-01-17 */ #ifndef TRIANGULATOR_H #define TRIANGULATOR_H #include "pandabase.h" #include "luse.h" #include "vector_int.h" /** * This class can triangulate a convex or concave polygon, even one with * holes. It is adapted from an algorithm published as: * * Narkhede A. and Manocha D., Fast polygon triangulation algorithm based on * Seidel's Algorithm, UNC-CH, 1994. * * http://www.cs.unc.edu/~dm/CODE/GEM/chapter.html * * It works strictly on 2-d points. See Triangulator3 for 3-d points. */ class EXPCL_PANDA_MATHUTIL Triangulator { PUBLISHED: Triangulator(); void clear(); int add_vertex(const LPoint2d &point); INLINE int add_vertex(double x, double y); INLINE int get_num_vertices() const; INLINE const LPoint2d &get_vertex(int n) const; MAKE_SEQ(get_vertices, get_num_vertices, get_vertex); MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex); void clear_polygon(); void add_polygon_vertex(int index); INLINE bool is_left_winding() const; void begin_hole(); void add_hole_vertex(int index); void triangulate(); int get_num_triangles() const; int get_triangle_v0(int n) const; int get_triangle_v1(int n) const; int get_triangle_v2(int n) const; protected: void cleanup_polygon_indices(vector_int &polygon); typedef pvector Vertices; Vertices _vertices; vector_int _polygon; typedef pvector Holes; Holes _holes; class Triangle { public: INLINE Triangle(Triangulator *t, int v0, int v1, int v2); int _v0, _v1, _v2; }; typedef pvector Result; Result _result; typedef struct { double x, y; } point_t, vector_t; struct segment_t { INLINE segment_t(); INLINE segment_t(Triangulator *t, int v0_i, int v1_i, int prev, int next); point_t v0, v1; /* two endpoints */ int is_inserted; /* inserted in trapezoidation yet ? */ int root0, root1; /* root nodes in Q */ int next; /* Next logical segment */ int prev; /* Previous segment */ int v0_i; // index to user's vertex number }; typedef pvector Segments; Segments seg; vector_int permute; int choose_idx; /* Trapezoid attributes */ typedef struct { int lseg, rseg; /* two adjoining segments */ point_t hi, lo; /* max/min y-values */ int u0, u1; int d0, d1; int sink; /* pointer to corresponding in Q */ int usave, uside; /* I forgot what this means */ int state; } trap_t; /* Node attributes for every node in the query structure */ typedef struct { int nodetype; /* Y-node or S-node */ int segnum; point_t yval; int trnum; int parent; /* doubly linked DAG */ int left, right; /* children */ } node_t; typedef struct { int vnum; int next; /* Circularly linked list */ int prev; /* describing the monotone */ int marked; /* polygon */ } monchain_t; typedef struct { point_t pt; int vnext[4]; /* next vertices for the 4 chains */ int vpos[4]; /* position of v in the 4 chains */ int nextfree; int user_i; // index to user's vertex number } vertexchain_t; typedef pvector QueryStructure; QueryStructure qs; typedef pvector TrapezoidStructure; TrapezoidStructure tr; /* Table to hold all the monotone */ /* polygons . Each monotone polygon */ /* is a circularly linked list */ pvector mchain; /* chain init. information. This */ /* is used to decide which */ /* monotone polygon to split if */ /* there are several other */ /* polygons touching at the same */ /* vertex */ pvector vert; /* contains position of any vertex in */ /* the monotone chain for the polygon */ vector_int mon; vector_int visited; bool check_left_winding(const vector_int &range) const; void make_segment(const vector_int &range, bool want_left_winding); int choose_segment(); static double math_log2(double v); static int math_logstar_n(int n); static int math_N(int n, int h); int newnode(); int newtrap(); int _max(point_t *yval, point_t *v0, point_t *v1); int _min(point_t *yval, point_t *v0, point_t *v1); int _greater_than(point_t *v0, point_t *v1); int _equal_to(point_t *v0, point_t *v1); int _greater_than_equal_to(point_t *v0, point_t *v1); int _less_than(point_t *v0, point_t *v1); int init_query_structure(int segnum); int is_left_of(int segnum, point_t *v); int inserted(int segnum, int whichpt); int locate_endpoint(point_t *v, point_t *vo, int r); int merge_trapezoids(int segnum, int tfirst, int tlast, int side); int add_segment(int segnum); int find_new_roots(int segnum); int construct_trapezoids(int nseg); int inside_polygon(trap_t *t); int newmon(); int new_chain_element(); double get_angle(point_t *vp0, point_t *vpnext, point_t *vp1); int get_vertex_positions(int v0, int v1, int *ip, int *iq); int make_new_monotone_poly(int mcur, int v0, int v1); int monotonate_trapezoids(int n); int traverse_polygon(int mcur, int trnum, int from, int dir); void triangulate_monotone_polygons(int nvert, int nmonpoly); void triangulate_single_polygon(int nvert, int posmax, int side); friend class Triangle; friend struct segment_t; }; #include "triangulator.I" #endif