All Downloads are FREE. Search and download functionalities are using the official Maven repository.

repicea.simulation.stemtaper.StemTaperSegment Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
/*
 * This file is part of the repicea-foresttools library.
 *
 * Copyright (C) 2009-2014 Mathieu Fortin for Rouge-Epicea
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed with 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 Lesser General Public
 * License for more details.
 *
 * Please see the license at http://www.gnu.org/copyleft/lesser.html.
 */
package repicea.simulation.stemtaper;

import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;

import repicea.math.integral.AbstractNumericalIntegrationMethod;
import repicea.math.integral.CompositeSimpsonRule;
import repicea.math.integral.TrapezoidalRule;

/**
 * The StemTaperSegment class represents a segment in the tree. It
 * provides two heights: one for the bottom cross section and a second
 * one for the top cross section.
 * @author Mathieu Fortin - July 2012
 */
public class StemTaperSegment {

	public static final double VERY_SMALL = 1E-3;

	private AbstractNumericalIntegrationMethod nim;
	
	/**
	 * Constructor 1.
	 * @param bottomCrossSection a double that represents the height of the lower cross section (m)
	 * @param topCrossSection a double that represents the height of the upper cross section (m)
	 * @param nim a NumericalIntegrationMethod instance
	 */
	public StemTaperSegment(double bottomCrossSection, double topCrossSection, AbstractNumericalIntegrationMethod nim) {
		if (bottomCrossSection > 0 && bottomCrossSection < topCrossSection) {
			nim.setLowerBound(bottomCrossSection);
			nim.setUpperBound(topCrossSection);
			this.nim = nim;
		} else {
			throw new InvalidParameterException("The bottom cross section is higher than the top section or its height is negative!");
		}
	}

	/**
	 * Constructor 2. 
	 * @param nim a NumericalIntegrationMethod instance that already contains the lower bound and upper bounds
	 */
	public StemTaperSegment(AbstractNumericalIntegrationMethod nim) {
		if (nim.getLowerBound() > 0 && nim.getLowerBound() < nim.getUpperBound()) {
			this.nim = nim;
		} else {
			throw new InvalidParameterException("The bottom cross section is higher than the top section or its height is negative!");
		}
	}
	
	
	/**
	 * Constructor 2.
	 * @param bottonStemTaperCrossSection a StemTaperCrossSection instance that represents the lower cross section
	 * @param topStemTaperCrossSection a StemTaperCrossSection instance that represents the upper cross section
	 * @param nim a NumericalIntegrationMethod instance
	 */
	protected StemTaperSegment(StemTaperCrossSection bottonStemTaperCrossSection, 
			StemTaperCrossSection topStemTaperCrossSection,
			AbstractNumericalIntegrationMethod nim) {
		this(bottonStemTaperCrossSection.getSectionHeight(), topStemTaperCrossSection.getSectionHeight(), nim);
	}

	/**
	 * This method returns the height (m) of the lower cross section.
	 * @return a double
	 */
	protected double getBottomHeight() {return nim.getLowerBound();}
	
	/**
	 * This method returns the height (m) of the upper cross section.
	 * @return a double
	 */
	protected double getTopHeight() {return nim.getUpperBound();}

	/**
	 * This method returns a List of Double that corresponds to the height for which
	 * the stem taper must be predicted. It depends on the integration method.
	 * @return a List of Double instances
	 */
	protected List getHeightsToEvaluate() {
		return nim.getXValues();
	}
	
	protected List getWeights() {
		return nim.getWeights();
	}
	
	protected List getRescalingFactors() {
		return nim.getRescalingFactors();
	}
	
	/**
	 * This method creates a StemTaperSegment with either a TrapezoidalRule or a CompositeSimpsonRule instance
	 * for numerical integration method.
	 * @param heights the list of heights in the segment (a List of Double instances)
	 * @param simpson true to use the CompositeSimpsonRule
	 * @param upToIndex the index in the heights to be considered
	 * @return a StemTaperSegment
	 */
	static StemTaperSegment createSegment(List heights, boolean simpson, int upToIndex) {
		if (simpson && upToIndex % 2 != 1) {
			upToIndex--;
		}
		List dumpList = new ArrayList();
		for (int i = 0; i < upToIndex; i++) {
			dumpList.add(heights.get(i));
		}
		StemTaperSegment segment;
		if (simpson) {
			segment = new StemTaperSegment(new CompositeSimpsonRule(dumpList));
		} else {
			segment = new StemTaperSegment(new TrapezoidalRule(dumpList));
		}
		dumpList.remove(dumpList.size() - 1);			// do not remove last element as it will serve for the next segment
		heights.removeAll(dumpList);
		return segment;
	}
	

	
//	public static void main(String[] args) {
//		List heights = new ArrayList();
//		heights.add(0.3);
//		heights.add(0.7);
//		heights.add(1.7);
//		heights.add(2.7);
//		heights.add(3.7);
//		heights.add(4.2);
//		StemTaperSegment.createStemTaperSegmentList(heights);
//	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy