/*
* curve.h
* DIN Is Noise is copyright (c) 2006-2024 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/


#ifndef __CURVE__
#define __CURVE__

#include <list>
#include <vector>

#include "crvpt.h"
#include "point.h"

struct curve {

	float x0, y0, x1, y1; // start/end points
	float tx0, ty0, tx1, ty1; // start/end tangents
	float ptx0, pty0; // start point to tangent vector
	float ptx1, pty1; // end point to tangent vector

  std::vector<crvpt> vpts; // bezier curve points for draw & solve
  std::vector<crvpt> dpts; // shapeform points (see multi_curve.h/cc)

  curve ();
  curve (float x0, float y0, float x1, float y1, float tx0, float ty0, float tx1, float ty1, float d = 0);
		
	/*
	 * din generates points on the bezier curve using recursive subdivision:
	 * 
	 * find midpoint of line joining end points
	 * if distance between midpoint on this line and point on the bezier curve > limit 
	 * insert point and repeat else stop
	*/ 
	
  float limit2; // square of limit distance
  void set_limit (float l);

	// evaluation generates points of the curve
	//
  enum {EVAL_COMPLETE, EVAL_REQUIRED};
  int eval_state;
	inline int eval_required () {return eval_state == EVAL_REQUIRED;}
	void eval (int find_length = 0);

	inline void vertex (int i, float xv, float yv) {
		if (i) {
			x1 = xv;
			y1 = yv;
			ptx1 = tx1 - x1;
			pty1 = ty1 - y1;
		} else {
			x0 = xv;
			y0 = yv;
			ptx0 = tx0 - x0;
			pty0 = ty0 - y0;
		}
		eval_state = EVAL_REQUIRED;
	}

	inline void get_vertex (int i, float& xv, float& yv) {
		if (i) {
			xv = x1;
			yv = y1;
		} else {
			xv = x0;
			yv = y0;
		}
	}

  inline void tangent (int i, float xt, float yt) {
		if (i) {
			tx1 = xt;
			ty1 = yt;
			ptx1 = tx1 - x1;
			pty1 = ty1 - y1;
		} else {
			tx0 = xt;
			ty0 = yt;
			ptx0 = tx0 - x0;
			pty0 = ty0 - y0;
		}
    eval_state = EVAL_REQUIRED;
  }

  inline void get_tangent (int i, float& xt, float& yt) {
		if (i) {
			xt = tx1;
			yt = ty1;
		} else {
			xt = tx0;
			yt = ty0;
		}
  }

	float length;
  float calc_length ();
  void normalise_length (float& now_length, float total_length);
  void calc_slope (crvpt& p, crvpt& q);

};

#endif
