public CS_SubsegmentImpl(Vector3 p, float r, float h, CS_SegmentImpl segment) { pos = p; rad = r; dist = h; this.segment = segment; }
/** * 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()); } } }
// makes the segments of the stem int makeSegments(int start_seg, int end_seg) { // if (start_seg>end_seg) throw new ArbaroException("Error in segment creation end_seg<start_seg."); if (stemlevel == 1) tree.updateGenProgress(); //if (par.verbose) { /* if (! pruneTest) { if (stemlevel==0) Console.progressChar('='); else if (stemlevel==1 && start_seg==0) Console.progressChar('/'); else if (stemlevel==2 && start_seg==0) Console.progressChar(); } //} */ DX_Transformation trf = transf; for (int s = start_seg; s < end_seg; s++) { if (stemlevel == 0) tree.updateGenProgress(); if (!pruneTest) {// && par.verbose) { //if (stemlevel==0) Console.progressChar('|'); } // curving trf = newDirection(trf, s); /* if (Console.debug()) TRF("Stem.make_segments(): after new_direction ",trf); */ // segment radius float rad1 = stemRadius(s * segmentLength); float rad2 = stemRadius((s + 1) * segmentLength); // create new segment CS_SegmentImpl segment = new CS_SegmentImpl(this, s, trf, rad1, rad2); segment.make(); segments.Add(segment); // create substems // self.DBG("SS-makingsubst? pt: %d, lev: %d\n"%(self.prunetest,self.level)) if (!pruneTest && lpar.level < par.Levels - 1) { // self.DBG("SS-making substems\n") makeSubstems(segment); } if (!pruneTest && lpar.level == par.Levels - 1 && par.Leaves != 0) { makeLeaves(segment); } // shift to next position trf = trf.translate(trf.getZ3()*(segmentLength)); //self.DBG("transf: %s\n"%(transf)) //self.DBG("pos: %s\n"%(transf.vector)) // test if too long if (pruneTest && !isInsideEnvelope(trf.getT())) { // DBG("PRUNE: not inside - return %d\n"%(s)) return s; } // splitting (create clones) if (s < end_seg - 1) { int segm = makeClones(trf, s); // trf is changed by make_clones // prune test - clone not inside envelope if (segm >= 0) { //DBG("PRUNE: clone not inside - return %d\n"%(segm)) return segm; } } } return -1; }
/** * Creates the leaves for the current stem segment * * @param segment */ void makeLeaves(CS_SegmentImpl segment) { // creates leaves for the current segment if (par.Leaves > 0) { // ### NORMAL MODE, leaves along the stem // how many leaves in this segment float leaves_eff = (int)(leavesPerSegment + par.leavesErrorValue + 0.5); // adapt error value par.leavesErrorValue -= (leaves_eff - leavesPerSegment); if (leaves_eff <= 0) return; float offs; if (segment.index == 0) { offs = parent.stemRadius(offset) / segmentLength; } else { offs = 0; } // what distance between the leaves float dist = (1.0f - offs) / leaves_eff; for (int s = 0; s < leaves_eff; s++) { // where on the segment add the leaf // FIXME: may be use the same distribution method (BranchDist) as for substems? float where = offs + dist / 2 + s * dist + lpar.var(dist / 2); // offset from stembase float loffs = (segment.index + where) * segmentLength; // get a new direction for the leaf DX_Transformation trf = substemDirection(segment.transf, loffs); // translate it to its position on the stem trf = trf.translate(segment.transf.getZ3()*(where * segmentLength)); // create new leaf CS_LeafImpl leaf = new CS_LeafImpl(trf); // ,loffs); leaf.make(par); leaves.Add(leaf); } } // ##### FAN MOD, leaves placed in a fan at stem end else if (par.Leaves < 0 && segment.index == segmentCount - 1) { CS_LevelParams lpar_1 = par.getLevelParams(stemlevel + 1); int cnt = (int)(leavesPerBranch() + 0.5); DX_Transformation trf = segment.transf.translate(segment.transf.getZ3()*(segmentLength)); float distangle = lpar_1.nRotate / cnt; float varangle = lpar_1.nRotateV / cnt; float downangle = lpar_1.nDownAngle; float vardown = lpar_1.nDownAngleV; float offsetangle = 0; // use different method for odd and even number if (cnt % 2 == 1) { // create one leaf in the middle CS_LeafImpl leaf = new CS_LeafImpl(trf); //,segmentCount*segmentLength); leaf.make(par); leaves.Add(leaf); offsetangle = distangle; } else { offsetangle = distangle / 2; } // create leaves left and right of the middle for (int s = 0; s < cnt / 2; s++) { for (int rot = 1; rot >= -1; rot -= 2) { DX_Transformation transf1 = trf.roty(rot * (offsetangle + s * distangle + lpar_1.var(varangle))); transf1 = transf1.rotx(downangle + lpar_1.var(vardown)); CS_LeafImpl leaf = new CS_LeafImpl(transf1); //,segmentCount*segmentLength); leaf.make(par); leaves.Add(leaf); } } } }
/** * 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()); } } }
// makes the segments of the stem int makeSegments(int start_seg, int end_seg) { // if (start_seg>end_seg) throw new ArbaroException("Error in segment creation end_seg<start_seg."); if (stemlevel == 1) { tree.updateGenProgress(); } //if (par.verbose) { /* * if (! pruneTest) { * if (stemlevel==0) Console.progressChar('='); * else if (stemlevel==1 && start_seg==0) Console.progressChar('/'); * else if (stemlevel==2 && start_seg==0) Console.progressChar(); * } * //} */ DX_Transformation trf = transf; for (int s = start_seg; s < end_seg; s++) { if (stemlevel == 0) { tree.updateGenProgress(); } if (!pruneTest) {// && par.verbose) { //if (stemlevel==0) Console.progressChar('|'); } // curving trf = newDirection(trf, s); /* * if (Console.debug()) * TRF("Stem.make_segments(): after new_direction ",trf); */ // segment radius float rad1 = stemRadius(s * segmentLength); float rad2 = stemRadius((s + 1) * segmentLength); // create new segment CS_SegmentImpl segment = new CS_SegmentImpl(this, s, trf, rad1, rad2); segment.make(); segments.Add(segment); // create substems // self.DBG("SS-makingsubst? pt: %d, lev: %d\n"%(self.prunetest,self.level)) if (!pruneTest && lpar.level < par.Levels - 1) { // self.DBG("SS-making substems\n") makeSubstems(segment); } if (!pruneTest && lpar.level == par.Levels - 1 && par.Leaves != 0) { makeLeaves(segment); } // shift to next position trf = trf.translate(trf.getZ3() * (segmentLength)); //self.DBG("transf: %s\n"%(transf)) //self.DBG("pos: %s\n"%(transf.vector)) // test if too long if (pruneTest && !isInsideEnvelope(trf.getT())) { // DBG("PRUNE: not inside - return %d\n"%(s)) return(s); } // splitting (create clones) if (s < end_seg - 1) { int segm = makeClones(trf, s); // trf is changed by make_clones // prune test - clone not inside envelope if (segm >= 0) { //DBG("PRUNE: clone not inside - return %d\n"%(segm)) return(segm); } } } return(-1); }
/** * Creates the leaves for the current stem segment * * @param segment */ void makeLeaves(CS_SegmentImpl segment) { // creates leaves for the current segment if (par.Leaves > 0) { // ### NORMAL MODE, leaves along the stem // how many leaves in this segment float leaves_eff = (int)(leavesPerSegment + par.leavesErrorValue + 0.5); // adapt error value par.leavesErrorValue -= (leaves_eff - leavesPerSegment); if (leaves_eff <= 0) { return; } float offs; if (segment.index == 0) { offs = parent.stemRadius(offset) / segmentLength; } else { offs = 0; } // what distance between the leaves float dist = (1.0f - offs) / leaves_eff; for (int s = 0; s < leaves_eff; s++) { // where on the segment add the leaf // FIXME: may be use the same distribution method (BranchDist) as for substems? float where = offs + dist / 2 + s * dist + lpar.var(dist / 2); // offset from stembase float loffs = (segment.index + where) * segmentLength; // get a new direction for the leaf DX_Transformation trf = substemDirection(segment.transf, loffs); // translate it to its position on the stem trf = trf.translate(segment.transf.getZ3() * (where * segmentLength)); // create new leaf CS_LeafImpl leaf = new CS_LeafImpl(trf); // ,loffs); leaf.make(par); leaves.Add(leaf); } } // ##### FAN MOD, leaves placed in a fan at stem end else if (par.Leaves < 0 && segment.index == segmentCount - 1) { CS_LevelParams lpar_1 = par.getLevelParams(stemlevel + 1); int cnt = (int)(leavesPerBranch() + 0.5); DX_Transformation trf = segment.transf.translate(segment.transf.getZ3() * (segmentLength)); float distangle = lpar_1.nRotate / cnt; float varangle = lpar_1.nRotateV / cnt; float downangle = lpar_1.nDownAngle; float vardown = lpar_1.nDownAngleV; float offsetangle = 0; // use different method for odd and even number if (cnt % 2 == 1) { // create one leaf in the middle CS_LeafImpl leaf = new CS_LeafImpl(trf); //,segmentCount*segmentLength); leaf.make(par); leaves.Add(leaf); offsetangle = distangle; } else { offsetangle = distangle / 2; } // create leaves left and right of the middle for (int s = 0; s < cnt / 2; s++) { for (int rot = 1; rot >= -1; rot -= 2) { DX_Transformation transf1 = trf.roty(rot * (offsetangle + s * distangle + lpar_1.var(varangle))); transf1 = transf1.rotx(downangle + lpar_1.var(vardown)); CS_LeafImpl leaf = new CS_LeafImpl(transf1); //,segmentCount*segmentLength); leaf.make(par); leaves.Add(leaf); } } } }