historical/toontown-classic.git/panda/include/triangulator.h
2024-01-16 11:20:27 -06:00

210 lines
5.7 KiB
C++

/**
* 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<LPoint2d> Vertices;
Vertices _vertices;
vector_int _polygon;
typedef pvector<vector_int> Holes;
Holes _holes;
class Triangle {
public:
INLINE Triangle(Triangulator *t, int v0, int v1, int v2);
int _v0, _v1, _v2;
};
typedef pvector<Triangle> 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<segment_t> 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<node_t> QueryStructure;
QueryStructure qs;
typedef pvector<trap_t> TrapezoidStructure;
TrapezoidStructure tr;
/* Table to hold all the monotone */
/* polygons . Each monotone polygon */
/* is a circularly linked list */
pvector<monchain_t> 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<vertexchain_t> 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