Пример #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
        public override Vector3[] getSectionPoints(bool start = true)
        {
            CS_Params      par  = segment.par;
            CS_LevelParams lpar = segment.lpar;

            int pt_cnt = lpar.mesh_points;

            Vector3[]         points;
            DX_Transformation trf = getTransformation(); //segment.getTransformation().translate(pos.sub(segment.getLowerPosition()));

            // if radius = 0 create only one point -> that's a problem for me
            if (false /*rad < -0.000001*/)
            {
                points    = new Vector3[1];
                points[0] = trf.apply(new Vector3(0, 0, 0));
            }
            else
            { //create pt_cnt points
                points = new Vector3[pt_cnt];
                //stem.DBG("MESH+LOBES: lobes: %d, depth: %f\n"%(self.tree.Lobes, self.tree.LobeDepth))

                for (int i = 0; i < pt_cnt; i++)
                {
                    float angle = i * 360.0f / pt_cnt;
                    // for Lobes ensure that points are near lobes extrema, but not exactly there
                    // otherwise there are to sharp corners at the extrema
                    if (lpar.level == 0 && par.Lobes != 0)
                    {
                        angle -= 10.0f / par.Lobes;
                    }

                    // create some point on the unit circle
                    Vector3 pt = new Vector3((float)Math.Cos(angle * Math.PI / 180), (float)Math.Sin(angle * Math.PI / 180), 0);
                    // scale it to stem radius
                    if (lpar.level == 0 && (par.Lobes != 0 || par._0ScaleV != 0))
                    {
                        float rad1 = rad * (1 +
                                            par.random.uniform(-par._0ScaleV, par._0ScaleV) /
                                            segment.getSubsegmentCount());
                        pt = pt * (rad1 * (1.0f + par.LobeDepth * (float)Math.Cos(par.Lobes * angle * Math.PI / 180.0)));
                    }
                    else
                    {
                        pt = pt * rad; // faster - no radius calculations
                    }
                    // apply transformation to it
                    // (for the first trunk segment transformation shouldn't be applied to
                    // the lower meshpoints, otherwise there would be a gap between
                    // ground and trunk)
                    // FIXME: for helical stems may be/may be not a random rotation
                    // should applied additionally?

                    pt        = trf.apply(pt);
                    points[i] = pt;
                }
            }

            return(points);
        }
Пример #3
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) /* 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);
        }
Пример #4
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();
        }
Пример #5
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;
            }
        }
Пример #6
0
        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);
        }
Пример #7
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));
        }
Пример #8
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());
                }
            }
        }
Пример #9
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);
                    }
                }
            }
        }