/** * Make a clone of the stem at this position * * @param trf The base transformation for the clone * @param start_segm Start segment number, i.e. the height, where * the clone spreads out * @return The clone stem object */ CS_StemImpl make_clone(DX_Transformation trf, int start_segm) { // creates a clone stem with same atributes as this stem CS_StemImpl clone = new CS_StemImpl(tree, this, stemlevel, trf, offset); clone.segmentLength = segmentLength; clone.segmentCount = segmentCount; clone.length = length; clone.baseRadius = baseRadius; clone.splitCorrection = splitCorrection; clone.pruneTest = pruneTest; clone.index = index; //DBG("Stem.clone(): clone_index "+clone_index); clone.cloneIndex.AddRange(cloneIndex); //DBG("Stem.clone(): level: "+stemlevel+" clones "+clones); clone.cloneIndex.Add(clones.Count); if (!pruneTest) { clone.lengthChildMax = lengthChildMax; //clone.substem_cnt = substem_cnt; clone.substemsPerSegment = substemsPerSegment; //clone.substemdist = substemdist; //clone.substemdistv = substemdistv; //clone.seg_splits = self.seg_splits // FIXME: for more then one clone this angle should somehow // correspond to the rotation angle of the clone clone.substemRotangle = substemRotangle + 180; clone.leavesPerSegment = leavesPerSegment; } return(clone); }
/* (non-Javadoc) * @see net.sourceforge.arbaro.tree.TraversableStem#getTreePosition() */ public override String getTreePosition() { // returns the position of the stem in the tree as a string, e.g. 0c0.1 // for the second substem of the first clone of the trunk CS_StemImpl stem = this; int lev = stemlevel; String pos = ""; while (lev >= 0) { if (stem.cloneIndex.Count > 0) { String clonestr = ""; for (int i = 0; i < stem.cloneIndex.Count; i++) { clonestr += "c" + ((int)stem.cloneIndex[i]).ToString(); } pos = "" + stem.index + clonestr + "." + pos; } else { pos = "" + stem.index + "." + pos; } if (lev > 0) { stem = stem.parent; } lev--; } if (pos[pos.Length - 1] == '.') { pos = pos.Substring(0, pos.Length - 1); } return(pos); }
/** * Sets (i.e. calcs) the progress for the process of making the tree * object. */ //long genProgress; // TODO ! synchronized //public synchronized void updateGenProgress() { public void updateGenProgress() { try { // how much of 0Branches*0CurveRes*(1Branches+1) are created yet long sum = 0; for (int i = 0; i < trunks.Count; i++) { CS_StemImpl trunk = ((CS_StemImpl)trunks[i]); if (trunk.substems != null) { sum += trunk.segments.Count * (trunk.substems.Count + 1); } else { sum += trunk.segments.Count; } } // TODO Progress /* * if (sum-genProgress > progress.getMaxProgress()/100) { * genProgress = sum; * progress.setProgress(genProgress); * }*/ } catch (Exception e) { Console.WriteLine(e.Message); } }
/** * Creates a new stem * * @param tr the tree object * @param params the general tree parameters * @param lparams the parameters for the stem level * @param parnt the parent stem, from wich the stems grows out * @param stlev the stem level * @param trf the base transformation of the stem * @param offs the offset of ste stem within the parent stem (0..1) */ public CS_StemImpl(CS_TreeImpl tr, CS_StemImpl growsOutOf, int stlev, DX_Transformation trf, float offs) /* offs=0 */ { tree = tr; stemlevel = stlev; transf = trf; offset = offs; if (growsOutOf != null) { if (growsOutOf.stemlevel < stemlevel) { parent = growsOutOf; } else { clonedFrom = growsOutOf; parent = growsOutOf.parent; } } par = tree.csparams; lpar = par.getLevelParams(stemlevel); // initialize lists segments = new List <CS_SegmentImpl>(lpar.nCurveRes); if (lpar.nSegSplits > 0 || par._0BaseSplits > 0) { clones = new List <CS_StemImpl>(); // lpar.nSegSplits*lpar.nCurveRes+1); } if (stemlevel < par.Levels - 1) { CS_LevelParams lpar_1 = par.getLevelParams(lpar.level + 1); substems = new List <CS_StemImpl>(lpar_1.nBranches); } if (stemlevel == par.Levels - 1 && par.Leaves != 0) { leaves = new List <CS_LeafImpl>(Math.Abs(par.Leaves)); } // inialize other variables leavesPerSegment = 0; splitCorrection = 0; index = 0; // substem number cloneIndex = new List <int>(); pruneTest = false; // flag used for pruning //... maxPoint = new Vector3(-float.MaxValue, -float.MaxValue, -float.MaxValue); minPoint = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); }
/* offs=0 */ /** * Creates a new stem * * @param tr the tree object * @param params the general tree parameters * @param lparams the parameters for the stem level * @param parnt the parent stem, from wich the stems grows out * @param stlev the stem level * @param trf the base transformation of the stem * @param offs the offset of ste stem within the parent stem (0..1) */ public CS_StemImpl(CS_TreeImpl tr, CS_StemImpl growsOutOf, int stlev, DX_Transformation trf, float offs) { tree = tr; stemlevel = stlev; transf = trf; offset = offs; if (growsOutOf != null) { if (growsOutOf.stemlevel < stemlevel) parent = growsOutOf; else { clonedFrom = growsOutOf; parent = growsOutOf.parent; } } par = tree.csparams; lpar = par.getLevelParams(stemlevel); // initialize lists segments = new List<CS_SegmentImpl>(lpar.nCurveRes); if (lpar.nSegSplits > 0 || par._0BaseSplits > 0) { clones = new List<CS_StemImpl>(); // lpar.nSegSplits*lpar.nCurveRes+1); } if (stemlevel < par.Levels - 1) { CS_LevelParams lpar_1 = par.getLevelParams(lpar.level + 1); substems = new List<CS_StemImpl>(lpar_1.nBranches); } if (stemlevel == par.Levels - 1 && par.Leaves != 0) { leaves = new List<CS_LeafImpl>(Math.Abs(par.Leaves)); } // inialize other variables leavesPerSegment = 0; splitCorrection = 0; index = 0; // substem number cloneIndex = new List<int>(); pruneTest = false; // flag used for pruning //... maxPoint = new Vector3(-float.MaxValue, -float.MaxValue, -float.MaxValue); minPoint = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); }
/** * Generates the tree. The following collaboration diagram * shows the recursion trough the make process: * <p> * <img src="doc-files/Tree-2.png" /> * <p> * * @throws Exception */ public void make(Object progress) { this.progress = progress; setupGenProgress(); csparams.prepare(seed); maxPoint = new Vector3(-float.MaxValue, -float.MaxValue, -float.MaxValue); minPoint = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Console.WriteLine("Tree species: " + csparams.Species + ", Seed: " + seed); Console.WriteLine("making " + csparams.Species + "(" + seed + ") "); // create the trunk and all its stems and leaves DX_Transformation transf = new DX_Transformation(); DX_Transformation trf; float angle; float dist; CS_LevelParams lpar = csparams.getLevelParams(0); for (int i = 0; i < lpar.nBranches; i++) { trf = trunkDirection(transf, lpar); angle = lpar.var(360); dist = lpar.var(lpar.nBranchDist); trf = trf.translate(new Vector3(dist * (float)Math.Sin(angle), dist * (float)Math.Cos(angle), 0)); CS_StemImpl trunk = new CS_StemImpl(this, null, 0, trf, 0); trunks.Add(trunk); trunk.index = 0; trunk.make(); } // set leafCount and stemCount for the tree if (csparams.Leaves == 0) { setLeafCount(0); } else { CS_LeafCounter leafCounter = new CS_LeafCounter(); traverseTree(leafCounter); setLeafCount(leafCounter.getLeafCount()); } CS_StemCounter stemCounter = new CS_StemCounter(); traverseTree(stemCounter); setStemCount(stemCounter.getStemCount()); // making finished Console.WriteLine("making " + csparams.Species + " Done. "); // TODO //progress.endPhase(); }
public CS_SegmentImpl(/*Params params, LevelParams lparams,*/ CS_StemImpl stm, int inx, DX_Transformation trf, float r1, float r2) { index = inx; transf = trf; rad1 = r1; rad2 = r2; stem = stm; par = stem.par; lpar = stem.lpar; length = stem.segmentLength; // FIXME: rad1 and rad2 could be calculated only when output occurs (?) // or here in the constructor ? // FIXME: inialize subsegs with a better estimation of size subsegments = new List <CS_SubsegmentImpl>(10); }
public CS_SegmentImpl(/*Params params, LevelParams lparams,*/ CS_StemImpl stm, int inx, DX_Transformation trf, float r1, float r2) { index = inx; transf = trf; rad1 = r1; rad2 = r2; stem = stm; par = stem.par; lpar = stem.lpar; length = stem.segmentLength; // FIXME: rad1 and rad2 could be calculated only when output occurs (?) // or here in the constructor ? // FIXME: inialize subsegs with a better estimation of size subsegments = new List<CS_SubsegmentImpl>(10); }
/** * Make a clone of the stem at this position * * @param trf The base transformation for the clone * @param start_segm Start segment number, i.e. the height, where * the clone spreads out * @return The clone stem object */ CS_StemImpl make_clone(DX_Transformation trf, int start_segm) { // creates a clone stem with same atributes as this stem CS_StemImpl clone = new CS_StemImpl(tree, this, stemlevel, trf, offset); clone.segmentLength = segmentLength; clone.segmentCount = segmentCount; clone.length = length; clone.baseRadius = baseRadius; clone.splitCorrection = splitCorrection; clone.pruneTest = pruneTest; clone.index = index; //DBG("Stem.clone(): clone_index "+clone_index); clone.cloneIndex.AddRange(cloneIndex); //DBG("Stem.clone(): level: "+stemlevel+" clones "+clones); clone.cloneIndex.Add(clones.Count); if (!pruneTest) { clone.lengthChildMax = lengthChildMax; //clone.substem_cnt = substem_cnt; clone.substemsPerSegment = substemsPerSegment; //clone.substemdist = substemdist; //clone.substemdistv = substemdistv; //clone.seg_splits = self.seg_splits // FIXME: for more then one clone this angle should somehow // correspond to the rotation angle of the clone clone.substemRotangle = substemRotangle + 180; clone.leavesPerSegment = leavesPerSegment; } return clone; }
/** * Make substems of the current stem * * @param segment */ void makeSubstems(CS_SegmentImpl segment) { // creates substems for the current segment CS_LevelParams lpar_1 = par.getLevelParams(stemlevel + 1); /* if (Console.debug()) DBG("Stem.make_substems(): substems_per_segment "+substemsPerSegment); */ float subst_per_segm; float offs; if (stemlevel > 0) { // full length of stem can have substems subst_per_segm = substemsPerSegment; if (segment.index == 0) { offs = parent.stemRadius(offset) / segmentLength; } else { offs = 0; } } else if (segment.index * segmentLength > par.BaseSize * length) { // segment is fully out of the bare trunk region => normal nb of substems subst_per_segm = substemsPerSegment; offs = 0; } else if ((segment.index + 1) * segmentLength <= par.BaseSize * length) { // segment is fully part of the bare trunk region => no substems return; } else { // segment has substems in the upper part only offs = (par.BaseSize * length - segment.index * segmentLength) / segmentLength; subst_per_segm = substemsPerSegment * (1 - offs); } // how many substems in this segment int substems_eff = (int)(subst_per_segm + lpar.substemErrorValue + 0.5); // adapt error value lpar.substemErrorValue -= (substems_eff - subst_per_segm); if (substems_eff <= 0) return; //DBG("Stem.make_substems(): substems_eff: "+substems_eff); // what distance between the segements substems float dist = (1.0f - offs) / substems_eff * lpar_1.nBranchDist; float distv = dist * 0.25f; // lpar_1.nBranchDistV/2; //DBG("Stem.make_substems(): offs: "+offs+" dist: "+dist+" distv: "+distv); for (int s = 0; s < substems_eff; s++) { // where on the segment add the substem float where = offs + dist / 2 + s * dist + lpar_1.var(distv); //offset from stembase float offset = (segment.index + where) * segmentLength; /* DBG("Stem.make_substems(): offset: "+ offset+" segminx: "+segment.index +" where: "+where+ " seglen: "+segmentLength); */ DX_Transformation trf = substemDirection(segment.transf, offset); trf = segment.substemPosition(trf, where); // create new substem CS_StemImpl substem = new CS_StemImpl(tree, this, stemlevel + 1, trf, offset); substem.index = substems.Count; //DBG("Stem.make_substems(): make new substem"); if (substem.make()) { substems.Add(substem); // //if (substem.segments.size()==0) // throw new ArbaroException("No segments created for substem "+substem.getTreePosition()); } } }
/** * Generates the tree. The following collaboration diagram * shows the recursion trough the make process: * <p> * <img src="doc-files/Tree-2.png" /> * <p> * * @throws Exception */ public void make(Object progress) { this.progress = progress; setupGenProgress(); csparams.prepare(seed); maxPoint = new Vector3(-float.MaxValue, -float.MaxValue, -float.MaxValue); minPoint = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Console.WriteLine("Tree species: " + csparams.Species + ", Seed: " + seed); Console.WriteLine("making " + csparams.Species + "(" + seed + ") "); // create the trunk and all its stems and leaves DX_Transformation transf = new DX_Transformation(); DX_Transformation trf; float angle; float dist; CS_LevelParams lpar = csparams.getLevelParams(0); for (int i = 0; i < lpar.nBranches; i++) { trf = trunkDirection(transf, lpar); angle = lpar.var(360); dist = lpar.var(lpar.nBranchDist); trf = trf.translate(new Vector3(dist * (float)Math.Sin(angle), dist * (float)Math.Cos(angle), 0)); CS_StemImpl trunk = new CS_StemImpl(this, null, 0, trf, 0); trunks.Add(trunk); trunk.index = 0; trunk.make(); } // set leafCount and stemCount for the tree if (csparams.Leaves == 0) setLeafCount(0); else { CS_LeafCounter leafCounter = new CS_LeafCounter(); traverseTree(leafCounter); setLeafCount(leafCounter.getLeafCount()); } CS_StemCounter stemCounter = new CS_StemCounter(); traverseTree(stemCounter); setStemCount(stemCounter.getStemCount()); // making finished Console.WriteLine("making " + csparams.Species + " Done. "); // TODO //progress.endPhase(); }
/** * Make substems of the current stem * * @param segment */ void makeSubstems(CS_SegmentImpl segment) { // creates substems for the current segment CS_LevelParams lpar_1 = par.getLevelParams(stemlevel + 1); /* * if (Console.debug()) * DBG("Stem.make_substems(): substems_per_segment "+substemsPerSegment); */ float subst_per_segm; float offs; if (stemlevel > 0) { // full length of stem can have substems subst_per_segm = substemsPerSegment; if (segment.index == 0) { offs = parent.stemRadius(offset) / segmentLength; } else { offs = 0; } } else if (segment.index * segmentLength > par.BaseSize * length) { // segment is fully out of the bare trunk region => normal nb of substems subst_per_segm = substemsPerSegment; offs = 0; } else if ((segment.index + 1) * segmentLength <= par.BaseSize * length) { // segment is fully part of the bare trunk region => no substems return; } else { // segment has substems in the upper part only offs = (par.BaseSize * length - segment.index * segmentLength) / segmentLength; subst_per_segm = substemsPerSegment * (1 - offs); } // how many substems in this segment int substems_eff = (int)(subst_per_segm + lpar.substemErrorValue + 0.5); // adapt error value lpar.substemErrorValue -= (substems_eff - subst_per_segm); if (substems_eff <= 0) { return; } //DBG("Stem.make_substems(): substems_eff: "+substems_eff); // what distance between the segements substems float dist = (1.0f - offs) / substems_eff * lpar_1.nBranchDist; float distv = dist * 0.25f; // lpar_1.nBranchDistV/2; //DBG("Stem.make_substems(): offs: "+offs+" dist: "+dist+" distv: "+distv); for (int s = 0; s < substems_eff; s++) { // where on the segment add the substem float where = offs + dist / 2 + s * dist + lpar_1.var(distv); //offset from stembase float offset = (segment.index + where) * segmentLength; /* * DBG("Stem.make_substems(): offset: "+ offset+" segminx: "+segment.index +" where: "+where+ " seglen: "+segmentLength); */ DX_Transformation trf = substemDirection(segment.transf, offset); trf = segment.substemPosition(trf, where); // create new substem CS_StemImpl substem = new CS_StemImpl(tree, this, stemlevel + 1, trf, offset); substem.index = substems.Count; //DBG("Stem.make_substems(): make new substem"); if (substem.make()) { substems.Add(substem); // //if (substem.segments.size()==0) // throw new ArbaroException("No segments created for substem "+substem.getTreePosition()); } } }
/** * Make clones of the current stem at the current segment * * @param trf The current segments's direction * @param nseg The number of the current segment * @return Segments outside the pruning envelope, -1 * if stem clone is completely inside the envelope */ int makeClones(DX_Transformation trf, int nseg) { // splitting // FIXME: maybe move this calculation to LevelParams // but pay attention to saving errorValues and restoring when making prune tests int seg_splits_eff; if (stemlevel == 0 && nseg == 0 && par._0BaseSplits > 0) { seg_splits_eff = par._0BaseSplits; } else { // how many clones? float seg_splits = lpar.nSegSplits; seg_splits_eff = (int)(seg_splits + lpar.splitErrorValue + 0.5); // adapt error value lpar.splitErrorValue -= (seg_splits_eff - seg_splits); } if (seg_splits_eff < 1) { return(-1); } float s_angle = 360 / (seg_splits_eff + 1); // make clones // if seg_splits_eff > 0: for (int i = 0; i < seg_splits_eff; i++) { // copy params CS_StemImpl clone = make_clone(trf, nseg + 1); // NOTE: its a little bit problematic here // when the clone is given as a parent to // the substems, it should have the same // params for length and segment_cnt like // the original stem, but this could be // somewhat confusing(?) // clone.segment_cnt = remaining_segs; // clone.length = remaining_segs * self.segment_len // change the direction for the clone //if self.debug: sys.stderr.write("-SPLIT_CORE_BEFOR: %s, dir: %s\n" % \ // (str(clone.split_corr),str(clone.direction))) clone.transf = clone.split(trf, s_angle * (1 + i), nseg, seg_splits_eff); //if self.debug: sys.stderr.write("-SPLIT_CORE_AFTER: %s, dir: %s\n" % // (str(clone.split_corr),str(clone.direction))) // make segments etc. for the clone int segm = clone.makeSegments(nseg + 1, clone.segmentCount); if (segm >= 0) { // prune test - clone not inside envelope return(segm); } // add clone to the list clones.Add(clone); } // get another direction for the original stem too trf = split(trf, 0, nseg, seg_splits_eff); return(-1); }