Пример #1
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()));
            }
        }
Пример #2
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);
        }
Пример #3
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);
        }
Пример #4
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);
        }