/** * Calcs the position of a substem in the segment given * a relativ position where in 0..1 - needed esp. for helical stems, * because the substems doesn't grow from the axis of the segement * * @param trf the transformation of the substem * @param where the offset, where the substem spreads out * @return the new transformation of the substem (shifted from * the axis of the segment to the axis of the subsegment) */ public DX_Transformation substemPosition(DX_Transformation trf, float where) { if (lpar.nCurveV >= 0) // normal segment { return(trf.translate(transf.getZ3() * (where * length))); } else // helix // get index of the subsegment { int i = (int)(where * (subsegments.Count - 1)); // interpolate position Vector3 p1 = ((CS_SubsegmentImpl)subsegments[i]).pos; Vector3 p2 = ((CS_SubsegmentImpl)subsegments[i + 1]).pos; Vector3 pos = p1 + (p2 - p1) * (where - i / (subsegments.Count - 1)); return(trf.translate(pos - getLowerPosition())); } }
// 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); } } } }