示例#1
0
        /* (non-Javadoc)
         * @see net.sourceforge.arbaro.tree.TraversableTree#traverseTree(net.sourceforge.arbaro.tree.TreeTraversal)
         */

        DX_Transformation trunkDirection(DX_Transformation trf, CS_LevelParams lpar)
        {
            // get rotation angle
            double rotangle;

            if (lpar.nRotate >= 0)
            { // rotating trunk
                trunk_rotangle = (trunk_rotangle + lpar.nRotate + lpar.var(lpar.nRotateV) + 360) % 360;
                rotangle       = trunk_rotangle;
            }
            else
            { // alternating trunks
                if (Math.Abs(trunk_rotangle) != 1)
                {
                    trunk_rotangle = 1;
                }
                trunk_rotangle = -trunk_rotangle;
                rotangle       = trunk_rotangle * (180 + lpar.nRotate + lpar.var(lpar.nRotateV));
            }

            // get downangle
            double downangle;

            downangle = lpar.nDownAngle + lpar.var(lpar.nDownAngleV);

            return(trf.rotxz(downangle, rotangle));
        }
示例#2
0
        /**
         * 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();
        }
示例#3
0
        /**
         * Calcs the direction of a substem from the parameters
         *
         * @param trf The transformation of the current stem segment
         * @param offset The offset of the substem from the base of the currents stem
         * @return The direction of the substem
         */

        DX_Transformation substemDirection(DX_Transformation trf, float offset)
        {
            CS_LevelParams lpar_1 = par.getLevelParams(stemlevel + 1);
            //lev = min(level+1,3);

            // get rotation angle
            float rotangle;

            if (lpar_1.nRotate >= 0)
            { // rotating substems
                substemRotangle = (substemRotangle + lpar_1.nRotate + lpar_1.var(lpar_1.nRotateV) + 360) % 360;
                rotangle        = substemRotangle;
            }
            else
            { // alternating substems
                if (Math.Abs(substemRotangle) != 1)
                {
                    substemRotangle = 1;
                }
                substemRotangle = -substemRotangle;
                rotangle        = substemRotangle * (180 + lpar_1.nRotate + lpar_1.var(lpar_1.nRotateV));
            }

            // get downangle
            float downangle;

            if (lpar_1.nDownAngleV >= 0)
            {
                downangle = lpar_1.nDownAngle + lpar_1.var(lpar_1.nDownAngleV);
            }
            else
            {
                float len = (stemlevel == 0) ? length * (1 - par.BaseSize) : length;
                downangle = lpar_1.nDownAngle +
                            lpar_1.nDownAngleV * (1 - 2 * par.getShapeRatio((length - offset) / len, 0));
            }

            /*
             * if (Console.debug())
             *  DBG("Stem.substem_direction(): down: "+downangle+" rot: "+rotangle);
             */
            return(trf.rotxz(downangle, rotangle));
        }
示例#4
0
        /**
         * Precalcs some stem parameters used later during when generating
         * the current stem
         */

        void prepareSubstemParams()
        {
            //int level = min(stemlevel+1,3);
            CS_LevelParams lpar_1 = par.getLevelParams(stemlevel + 1);

            // maximum length of a substem
            lengthChildMax = lpar_1.nLength + lpar_1.var(lpar_1.nLengthV);

            // maximum number of substems
            float stems_max = lpar_1.nBranches;

            // actual number of substems and substems per segment
            float substem_cnt;

            if (stemlevel == 0)
            {
                substem_cnt        = stems_max;
                substemsPerSegment = (float)(substem_cnt / (float)segmentCount / (1 - par.BaseSize));

                /*
                 * if (Console.debug())
                 *  DBG("Stem.prepare_substem_params(): stems_max: "+ substem_cnt
                 + " substems_per_segment: " + substemsPerSegment);
                 */
            }
            else if (par.preview)
            {
                substem_cnt        = stems_max;
                substemsPerSegment = (float)(substem_cnt / segmentCount);
            }
            else if (stemlevel == 1)
            {
                substem_cnt = (int)(stems_max *
                                    (0.2 + 0.8 * length / parent.length / parent.lengthChildMax));
                substemsPerSegment = substem_cnt / (float)segmentCount;

                /*DBG("Stem.prepare_substem_params(): substem_cnt: "+ substem_cnt
                 + " substems_per_segment: " + substemsPerSegment);*/
            }
            else
            {
                substem_cnt        = (int)(stems_max * (1.0 - 0.5 * offset / parent.length));
                substemsPerSegment = substem_cnt / (float)segmentCount;
            }
            substemRotangle = 0;

            // how much leaves for this stem - not really a substem parameter
            if (lpar.level == par.Levels - 1)
            {
                leavesPerSegment = leavesPerBranch() / segmentCount;
            }
        }
示例#5
0
        /**
         * Calcs stem length from parameters and parent length
         *
         * @return the stem length
         */

        float stemLength()
        {
            if (stemlevel == 0)
            { // trunk
                return((lpar.nLength + lpar.var(lpar.nLengthV)) * par.scale_tree);
            }
            else if (stemlevel == 1)
            {
                float parlen  = parent.length;
                float baselen = par.BaseSize * par.scale_tree;
                float ratio   = (parlen - offset) / (parlen - baselen);

                /*
                 * if (Console.debug())
                 *  DBG("Stem.stem_length(): parlen: "+parlen+" offset: "+offset+" baselen: "+baselen+" ratio: "+ratio);
                 */
                return(parlen * parent.lengthChildMax * par.getShapeRatio(ratio));
            }
            else
            { // higher levels
                return((float)(parent.lengthChildMax * (parent.length - 0.6 * offset)));
            }
        }
示例#6
0
        /**
         * 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());
                }
            }
        }
示例#7
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);
                    }
                }
            }
        }