/**
         * 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()));
            }
        }
Beispiel #2
0
        // 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);
        }
Beispiel #3
0
        /**
         * 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);
                    }
                }
            }
        }