Exemplo n.º 1
0
        /**
         * Make a clone of the stem at this position
         *
         * @param trf The base transformation for the clone
         * @param start_segm Start segment number, i.e. the height, where
         *        the clone spreads out
         * @return The clone stem object
         */

        CS_StemImpl make_clone(DX_Transformation trf, int start_segm)
        {
            // creates a clone stem with same atributes as this stem
            CS_StemImpl clone = new CS_StemImpl(tree, this, stemlevel, trf, offset);

            clone.segmentLength   = segmentLength;
            clone.segmentCount    = segmentCount;
            clone.length          = length;
            clone.baseRadius      = baseRadius;
            clone.splitCorrection = splitCorrection;
            clone.pruneTest       = pruneTest;
            clone.index           = index;

            //DBG("Stem.clone(): clone_index "+clone_index);
            clone.cloneIndex.AddRange(cloneIndex);

            //DBG("Stem.clone(): level: "+stemlevel+" clones "+clones);
            clone.cloneIndex.Add(clones.Count);
            if (!pruneTest)
            {
                clone.lengthChildMax = lengthChildMax;
                //clone.substem_cnt = substem_cnt;
                clone.substemsPerSegment = substemsPerSegment;
                //clone.substemdist = substemdist;
                //clone.substemdistv = substemdistv;
                //clone.seg_splits = self.seg_splits
                // FIXME: for more then one clone this angle should somehow
                // correspond to the rotation angle of the clone
                clone.substemRotangle  = substemRotangle + 180;
                clone.leavesPerSegment = leavesPerSegment;
            }
            return(clone);
        }
Exemplo n.º 2
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));
        }
Exemplo n.º 3
0
        public override bool visitLeaf(CS_Leaf leaf)
        {
            DX_Transformation transf = leaf.getTransformation();

            List <DXMEV> mev = new List <DXMEV>();

            foreach (DXMEV m in V)
            {
                DXMEV mp = new DXMEV();
                mp.P = transf.apply(m.P);
                mp.P = new Vector4(mp.P.X, mp.P.Z, mp.P.Y, 1);
                mev.Add(mp);

                BBox.Maximum = Vector3.Max(BBox.Maximum, new Vector3(mp.P.X, mp.P.Y, mp.P.Z));
                BBox.Minimum = Vector3.Min(BBox.Minimum, new Vector3(mp.P.X, mp.P.Y, mp.P.Z));
            }

            int c = Vertices2[LEAFLEVEL].Count;

            foreach (int k in I)
            {
                Indices2[LEAFLEVEL].Add(c + k);
            }

            Vertices2[LEAFLEVEL].AddRange(mev);

            return(true);
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
            public override bool visitLeaf(CS_Leaf leaf)
            {
                DX_Transformation transf = leaf.getTransformation();

                _lmh.AddLeaf(transf);

                return(true);
            }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
0
        /**
         * Gives a clone a new direction (splitting)
         *
         * @param trf The base transformation of the clone
         * @param s_angle The splitting angle
         * @param nseg The segment number, where the clone begins
         * @param nsplits The number of clones
         * @return The new direction for the clone
         */

        DX_Transformation split(DX_Transformation trf,
                                float s_angle, int nseg, int nsplits)
        {
            // applies a split angle to the stem - the Weber/Penn method
            int remaining_seg = segmentCount - nseg - 1;

            // the splitangle
            // FIXME: don't know if it should be nSplitAngle or nSplitAngle/2
            float declination = (float)(Math.Acos(trf.getZ3().Z) * 180 / Math.PI);
            float split_angle = Math.Max(0, (lpar.nSplitAngle
                                             + lpar.var(lpar.nSplitAngleV) - declination));

            // FIXME: first works better for level 0, second for further levels
            // transf = transf.rotxz(split_angle,s_angle)
            trf = trf.rotx(split_angle);

            // adapt split correction
            splitCorrection -= split_angle / remaining_seg;
            //t_corr = Transformation().rotx(-split_angle/remaining_seg)

            float split_diverge;

            if (s_angle > 0)
            { // original stem has s_angle==0
                if (par._0BaseSplits > 0 && stemlevel == 0 && nseg == 0)
                {
                    split_diverge = s_angle + lpar.var(lpar.nSplitAngleV);
                }
                else
                {
                    split_diverge = (float)(20 + 0.75 * (30 + Math.Abs(declination - 90))
                                            * Math.Pow((lpar.var(1) + 1) / 2.0, 2));
                    if (lpar.var(1) >= 0)
                    {
                        split_diverge = -split_diverge;
                    }
                }

                trf = trf.rotaxis(split_diverge, DX_Transformation.Z_AXIS);
            }
            else
            {
                split_diverge = 0;  // for debugging only
            }
            // adjust some parameters
            //split_cnt = split_cnt+1;

            // lower substem prospensity
            if (!pruneTest)
            {
                substemsPerSegment /= (float)(nsplits + 1);
                // FIXME: same reduction for leaves_per_segment?
            }
            return(trf);
        }
Exemplo n.º 8
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();
        }
 public void AddLeaf(DX_Transformation transf)
 {
     if (_leafType == 0)
     {
         MakeDiscPoints(5, transf);
     }
     else if (_leafType == 1)
     {
         MakeDiscPoints(3, transf);
     }
     else if (_leafType == 2)
     {
         MakeDiscPoints(4, transf);
     }
     else if (_leafType == 3)
     {
         MakeDiscPoints(5, transf);
     }
     else if (_leafType == 4)
     {
         MakeDiscPoints(6, transf);
     }
     else if (_leafType == 5)
     {
         MakeDiscPoints(7, transf);
     }
     else if (_leafType == 6)
     {
         MakeDiscPoints(8, transf);
     }
     else if (_leafType == 7)
     {
         MakeDiscPoints(9, transf);
     }
     else if (_leafType == 8)
     {
         MakeDiscPoints(10, transf);
     }
     else if (_leafType == 9)
     {
         MakeDiscPoints(11, transf);
     }
     else if (_leafType == 10)
     {
         MakeDiscPoints(4, transf);
     }
     //else if (_leafType == 11) MakeSpherePoints();
 }
Exemplo n.º 10
0
        /**
         * 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()));
            }
        }
Exemplo n.º 11
0
        /**
         *	Leaf rotation toward light
         */
        private void setLeafOrientation(CS_Params par)
        {
            if (par.LeafBend == 0)
            {
                return;
            }

            // FIXME: make this function as fast as possible - a tree has a lot of leafs

            // rotation outside
            Vector3 pos = transf.getT();
            // the z-vector of transf is parallel to the
            // axis of the leaf, the y-vector is the normal
            // (of the upper side) of the leaf
            Vector3 norm = transf.getY3();

            float tpos  = (float)(Math.Atan2(pos.Y, pos.X) * 180 / Math.PI);
            float tbend = tpos - (float)(Math.Atan2(norm.Y, norm.X) * 180 / Math.PI);;
            // if (tbend>180) tbend = 360-tbend;

            float bend_angle = par.LeafBend * tbend;

            // transf = transf.rotz(bend_angle);
            // rotate about global z-axis
            transf = transf.rotaxis(bend_angle, DX_Transformation.Z_AXIS);

            // rotation up
            norm = transf.getY3();
            float fbend = (float)(Math.Atan2((float)Math.Sqrt(norm.X * norm.X + norm.Y * norm.Y), norm.Z) * 180 / Math.PI);

            bend_angle = par.LeafBend * fbend;

            transf = transf.rotx(bend_angle);

            //		this is from the paper, but is equivalent with
            //      local x-rotation (upper code line)
            //
            //		double orientation = Vector.atan2(norm.getY(),norm.getX());
            //		transf = transf
            //			.rotaxis(-orientation,Vector.Z_AXIS)
            //			.rotx(bend_angle)
            //			.rotaxis(orientation,Vector.Z_AXIS);
        }
Exemplo n.º 12
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);
        }
Exemplo n.º 13
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));
        }
        private void MakeDiscPoints(int vCount, DX_Transformation transf)
        {
            List <DXBaseArbaroTreeMesh.DXVertex> dxvv = new List <DXBaseArbaroTreeMesh.DXVertex>();

            // Create vertices
            for (int i = 0; i < vCount; i++)
            {
                float   a = (float)(i * Math.PI * 2 / vCount);
                Vector4 p = new Vector4((float)Math.Sin(a), 0, (float)Math.Cos(a), 1);

                if (a < Math.PI)
                {
                    p.X -= leaffunc(a);
                }
                else if (a > Math.PI)
                {
                    p.X += leaffunc((float)(2 * Math.PI - a));
                }

                p.X *= _width;
                p.Y *= _width;
                p.Z  = (_stemLength + p.Z + 1) * _length;

                p = transf.apply(p);

                DXBaseArbaroTreeMesh.DXVertex dxv = _mesh.Vertices.Add(new DXArbaroVertexTrait(new Vector3(p.X, p.Y, p.Z)));
                dxvv.Add(dxv);
            }

            // create faces
            for (int i = 0; i < vCount - 2; i++)
            {
                //Console.WriteLine(dxvv[0].Index + " " + dxvv[i + 1].Index + " " + dxvv[i + 2].Index);
                _mesh.Faces.Add(dxvv[0], dxvv[i + 1], dxvv[i + 2]);
            }
        }
Exemplo n.º 15
0
        public override bool visitLeaf(CS_Leaf leaf)
        {
            DXSKV             v0, v1;
            DX_Transformation transf = leaf.getTransformation();


            // the tree is caculated in openGL coordinates with Z "up" so...
            v0.P = new Vector3(0, 0, 0);
            v1.P = new Vector3(0, 0, _csParams.LeafScale);
            v0.P = transf.apply(v0.P); v0.P = new Vector3(v0.P.X, v0.P.Z, v0.P.Y);
            v1.P = transf.apply(v1.P); v1.P = new Vector3(v1.P.X, v1.P.Z, v1.P.Y);
            v0.C = colors[5];
            v1.C = colors[5];

            BBox.Maximum = Vector3.Max(BBox.Maximum, v0.P);
            BBox.Maximum = Vector3.Max(BBox.Maximum, v1.P);
            BBox.Minimum = Vector3.Min(BBox.Minimum, v0.P);
            BBox.Minimum = Vector3.Min(BBox.Minimum, v1.P);

            Vertices2[LEAFLEVEL].Add(v0);
            Vertices2[LEAFLEVEL].Add(v1);

            return(true);
        }
Exemplo n.º 16
0
        /**
         * Make clones of the current stem at the current segment
         *
         * @param trf The current segments's direction
         * @param nseg The number of the current segment
         * @return Segments outside the pruning envelope, -1
         *         if stem clone is completely inside the envelope
         */

        int makeClones(DX_Transformation trf, int nseg)
        {
            // splitting
            // FIXME: maybe move this calculation to LevelParams
            // but pay attention to saving errorValues and restoring when making prune tests
            int seg_splits_eff;

            if (stemlevel == 0 && nseg == 0 && par._0BaseSplits > 0)
            {
                seg_splits_eff = par._0BaseSplits;
            }
            else
            {
                // how many clones?
                float seg_splits = lpar.nSegSplits;
                seg_splits_eff = (int)(seg_splits + lpar.splitErrorValue + 0.5);

                // adapt error value
                lpar.splitErrorValue -= (seg_splits_eff - seg_splits);
            }

            if (seg_splits_eff < 1)
            {
                return(-1);
            }

            float s_angle = 360 / (seg_splits_eff + 1);

            // make clones
            // if seg_splits_eff > 0:
            for (int i = 0; i < seg_splits_eff; i++)
            {
                // copy params
                CS_StemImpl clone = make_clone(trf, nseg + 1);

                // NOTE: its a little bit problematic here
                // when the clone is given as a parent to
                // the substems, it should have the same
                // params for length and segment_cnt like
                // the original stem, but this could be
                // somewhat confusing(?)
                // clone.segment_cnt = remaining_segs;
                // clone.length = remaining_segs * self.segment_len

                // change the direction for the clone
                //if self.debug: sys.stderr.write("-SPLIT_CORE_BEFOR: %s, dir: %s\n" % \
                //	(str(clone.split_corr),str(clone.direction)))

                clone.transf = clone.split(trf, s_angle * (1 + i), nseg, seg_splits_eff);

                //if self.debug: sys.stderr.write("-SPLIT_CORE_AFTER: %s, dir: %s\n" %
                //	(str(clone.split_corr),str(clone.direction)))

                // make segments etc. for the clone
                int segm = clone.makeSegments(nseg + 1, clone.segmentCount);
                if (segm >= 0)
                { // prune test - clone not inside envelope
                    return(segm);
                }
                // add clone to the list
                clones.Add(clone);
            }
            // get another direction for the original stem too
            trf = split(trf, 0, nseg, seg_splits_eff);
            return(-1);
        }
Exemplo n.º 17
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());
                }
            }
        }
Exemplo n.º 18
0
        /**
         * Calcs a new direction for the current segment
         *
         * @param trf The transformation of the previous segment
         * @param nsegm The number of the segment ( for testing, if it's the
         *              first stem segment
         * @return The new transformation of the current segment
         */

        DX_Transformation newDirection(DX_Transformation trf, int nsegm)
        {
            // next segments direction

            // The first segment shouldn't get another direction
            // down and rotation angle shouldn't be falsified
            if (nsegm == 0)
            {
                return(trf);
            }

            /*
             * if (Console.debug())
             *  TRF("Stem.new_direction() before curving",trf);
             */

            // get curving angle
            double delta;

            if (lpar.nCurveBack == 0)
            {
                delta = lpar.nCurve / lpar.nCurveRes;
            }
            else
            {
                if (nsegm < (lpar.nCurveRes + 1) / 2)
                {
                    delta = lpar.nCurve * 2 / lpar.nCurveRes;
                }
                else
                {
                    delta = lpar.nCurveBack * 2 / lpar.nCurveRes;
                }
            }
            delta += splitCorrection;

            /*
             * if (Console.debug())
             *  DBG("Stem.new_direction(): delta: "+delta);
             */

            trf = trf.rotx(delta);


            // With Weber/Penn the orientation of the x- and y-axis
            // shouldn't be disturbed (maybe, because proper curving relies on this)
            // so may be such random rotations shouldn't be used, instead nCurveV should
            // add random rotation to rotx, and rotate nCurveV about the tree's z-axis too?

            // add random rotation about z-axis
            if (lpar.nCurveV > 0)
            {
                //          if (nsegm==0 && stemlevel==0) { // first_trunk_segment
                //              // random rotation more moderate
                //              delta = (Math.abs(lpar.var(lpar.nCurveV)) -
                //                      Math.abs(lpar.var(lpar.nCurveV)))
                //						/ lpar.nCurveRes;
                //          }	else {
                // full random rotation
                delta = lpar.var(lpar.nCurveV) / lpar.nCurveRes;
                //          }
                // self.DBG("curvV (delta): %s\n" % str(delta))
                double rho = 180 + lpar.var(180);
                trf = trf.rotaxisz(delta, rho);
            }
            //TRF("Stem.new_direction() after curving",trf);

            // attraction up/down
            if (par.AttractionUp != 0 && stemlevel >= 2)
            {
                double declination = Math.Acos(trf.getZ3().Z);

                //          I don't see, why we need orientation here, may be this avoids
                //          attraction of branches with the x-Axis up and thus avoids
                //			twisting (see below), but why branches in one direction should
                //			be attracted, those with another direction not, this is unnaturally:
                //          double orient = Math.acos(trf.getY().getZ());
                //          double curve_up_orig = par.AttractionUp * declination * Math.cos(orient)/lpar.nCurveRes;

                // FIXME: devide by (lpar.nCurveRes-nsegm) if last segment
                // should actually be vertical
                double curve_up = par.AttractionUp *
                                  Math.Abs(declination * Math.Sin(declination)) / lpar.nCurveRes;

                Vector3 z = trf.getZ3();
                // FIXME: the mesh is twisted for high values of AttractionUp
                trf = trf.rotaxis(-curve_up * 180 / Math.PI, new Vector3(-z.Y, z.X, 0));
                // trf = trf.rotx(curve_up*180/Math.PI);
            }
            return(trf);
        }
Exemplo n.º 19
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);
        }
Exemplo n.º 20
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);
                    }
                }
            }
        }
Exemplo n.º 21
0
        /**
         * For debugging:
         * Prints out the transformation to stderr nicely
         * (only if debugging is enabled)
         *
         * @param where The position in the tree, i.e. wich stem
         *              has this transformation
         * @param trf  The transformation
         */

        void TRF(String where, DX_Transformation trf)
        {
            //DBG(where + ": " + trf.toString());
        }
Exemplo n.º 22
0
 public CS_LeafImpl(DX_Transformation trf)
 {
     //		par = params;
     transf = trf;
 }