/*****************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                          */
/* ************************************************************* */

// decomposite.cpp
// implementation for functions about decomposition
#include "stdafx.h"
#include "Calc/decomposite.h"

#include "mg/CompositeCurve.h"
#include "mg/Straight.h"
#include "mg/Group.h"
#include "topo/Shell.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

namespace mgcalc{
	namespace detail{
		// decomposite a composite curve into its components
		void decomposite(const MGCompositeCurve& c, MGGroup& g){
			int i = c.number_of_curves();
			while(i--){
				MGCurve* ci = c.curve(i).clone();
				ci->copy_appearance(c);
				g.append(ci);
			}
		}

		// decomposite a shell into its components
		void decomposite(const MGShell& she, MGGroup& g){
			int i = she.number_of_faces();
			while(i--){
				MGFace* fi = she.face(i)->clone();
				fi->copy_appearance(she);
				g.append(fi);
			}
		}
	}

	// Releases elements of a composite object, or decomposite a polyline
	// into straight segments.
	bool decomposite(
		const MGObject& obj,   // composite object. e.g., MGCompositeCurve, MGShell.
		MGGroup&        output // to which the resulting components are inserted
	){
		const MGShell* shel = dynamic_cast<const MGShell*>(&obj);
		if(shel){
			detail::decomposite(*shel, output);
			return true;
		}

		const MGCurve* c = dynamic_cast<const MGCurve*>(&obj);
		if(c){
			if(const MGCompositeCurve* c2 = dynamic_cast<const MGCompositeCurve*>(c)){
				detail::decomposite(*c2, output);
				return true;
			}

			if(c->type() == MGCURVE_SPLINE){// special case
				// decomposite a polyline into straight segments.
				const MGKnotVector& t = c->knot_vector();
				if(t.order() == 2 && t.bdim() >= 3){
					for(int i = 1; i < t.bdim(); i++){
						MGStraight* line = new MGStraight(c->eval(t[i]), c->eval(t[i+1]));
						output.append(line);
					}
					return true;
				}
			}
		}
		return false;
	}
}
