/// <summary>
 /// Creates a 2D rotation.
 /// </summary>
 /// <param name="angle">The angle in radians.</param>
 /// <returns></returns>
 public static TikzMatrix RotationMatrix(double angle)
 {
     TikzMatrix ret = new TikzMatrix();
     ret.m[0, 0] = ret.m[1, 1] =Math.Cos(angle);
     ret.m[0, 1] = -Math.Sin(angle);
     ret.m[1, 0] = -ret.m[0, 1];
     return ret;
 }
        public Parser.TikzMatrix GetTikzToScreenTransform()
        {
            Parser.TikzMatrix AbsTikzToScreen = new Parser.TikzMatrix();
            AbsTikzToScreen.m[0, 0] = View.Resolution;
            AbsTikzToScreen.m[1, 1] = -View.Resolution;
            AbsTikzToScreen.m[0, 2] = -View.Resolution * View.BB.X;
            AbsTikzToScreen.m[1, 2] = View.Resolution * (View.BB.Height + View.BB.Y);

            Parser.TikzMatrix total = AbsTikzToScreen * View.CoordinateTransform;
            return total;
        }
        public TikzMatrix Inverse()
        {
            TikzMatrix mi = new TikzMatrix();
            double d = Det();
            mi.m[0,0] = m[1, 1] / d;
            mi.m[1, 0] = -m[1, 0] / d;
            mi.m[0, 1] = -m[0, 1] / d;
            mi.m[1, 1] = m[0, 0] / d;

            mi.m[0, 2] = - mi.m[0,0] * m[0,2] - mi.m[0,1]*m[1,2];
            mi.m[1, 2] = - mi.m[1,0] * m[0, 2] - mi.m[1, 1] * m[1, 2];

            return mi;
        }
 public static TikzMatrix ZeroMatrix()
 {
     TikzMatrix ret = new TikzMatrix();
     ret.m[0, 0] = 0; ret.m[1, 1] = 0;
     return ret;
 }
        /// <summary>
        /// Same as above, but additionally the editable shift is returned.
        /// (or null if a new one needs to be created)
        /// </summary>
        /// <param name="ret"></param>
        /// <param name="EditableShift"></param>
        /// <returns></returns>
        bool GetTransformAtEditableShift(out TikzMatrix ret, out Tikz_Option EditableShift)
        {
            ret = new TikzMatrix();     // stores the coord trsf. at current position
            EditableShift = null;
            if (!parent.GetCurrentTransformAt(this, out ret))
                return false;
            //bool foundone = false;
            foreach (TikzParseItem tpi in Children)
            {
                if (tpi is Tikz_Option)
                {
                    Tikz_Option to = tpi as Tikz_Option;

                    if (to.type == Tikz_OptionType.keyval && to.key.Trim() == "shift")
                    {
                        if (to.coordval == null)
                            return false;
                        if (to.coordval.type == Tikz_CoordType.Cartesian)
                        {
                            // we found one (yoohoo)
                            EditableShift = to;
                            return true;
                        }
                    }

                    if (!TransformFromOption(to, ret, out ret))
                        return false; // invalid coord trafo encountered -> report failure
                }
            }

            EditableShift = null;   // nothing found -> return null
            return true;
        }
 /// <summary>
 /// It returns, if possible, the coordinate transformation at the shift=... option that will
 /// be editted by SetShiftRel(). This method is in particular used by PdfOverlay to draw the raster associated 
 /// to a scope object. 
 /// </summary>
 /// <param name="ret"></param>
 /// <returns>true on success, false if coord trafo could not be determined</returns>
 public bool GetTransformAtEditableShift(out TikzMatrix ret)
 {
     Tikz_Option dummy;
     return GetTransformAtEditableShift(out ret, out dummy);
 }
        /// <summary>
        /// Returns the coordinate transfor corresponding to an option, if possible.
        /// If the option is not relevant for coordinate tranformation (or not supported), true is returned 
        /// and newTrafo = oldTrafo. If the option is recognized, but the value cannot be determined,
        /// false is returned and newTrafo shouldn't be used.
        /// </summary>
        /// <param name="to"></param>
        /// <param name="oldTrafo"></param>
        /// <param name="newTrafo"></param>
        /// <returns></returns>
        bool TransformFromOption(Tikz_Option to, TikzMatrix oldTrafo, out TikzMatrix newTrafo)
        {
            TikzMatrix ret = new TikzMatrix();
            newTrafo = ret;
            if (to.type == Tikz_OptionType.keyval)
            {
                switch (to.key.Trim())
                {
                    case "xscale":
                        if (to.numval == null)
                            return false;
                        ret.m[0, 0] = to.numval.GetInCM();
                        break;
                    case "yscale":
                        if (to.numval == null)
                            return false;
                        ret.m[1, 1] = to.numval.GetInCM();
                        break;
                    case "scale":
                        if (to.numval == null)
                            return false;
                        ret.m[0, 0] = to.numval.GetInCM();
                        ret.m[1, 1] = ret.m[0, 0];
                        break;
                    case "xshift":
                        if (to.numval == null)
                            return false;
                        ret.m[0, 2] = to.numval.GetInCM("pt");
                        break;
                    case "yshift":
                        if (to.numval == null)
                            return false;
                        ret.m[1, 2] = to.numval.GetInCM("pt");
                        break;
                    case "shift":
                        // shift is complicated.....
                        if (to.coordval == null)
                            return false;
                        if (to.coordval.type == Tikz_CoordType.Named)
                        {
                            // for named coord, shift sets the _absolute_ origin of the coord system
                            // hence we need the absolute coord trafo at the current point!
                            Point neworig;
                            if (!to.coordval.GetAbsPos(out neworig, this))
                                return false;

                            TikzMatrix Mabs;
                            if (!parent.GetCurrentTransformAt(this, out Mabs))
                                return false;

                            Mabs = Mabs * oldTrafo;
                            Point theshift = Mabs.Inverse().Transform(neworig);
                            ret.m[0, 2] = theshift.X;
                            ret.m[1, 2] = theshift.Y;

                        }
                        else if (to.coordval.type == Tikz_CoordType.Cartesian || to.coordval.type == Tikz_CoordType.Polar)
                        {
                            Point p = to.coordval.GetCartesian();
                            ret.m[0, 2] = p.X;
                            ret.m[1, 2] = p.Y;
                        }
                        else
                        {
                            // invalid coordinate value
                            return false;
                        }                        
                        break;
                    case "rotate":
                        if (to.numval == null)
                            return false;
                        double angle = to.numval.GetInCM() * 2* Math.PI / 360;
                        ret.m[0, 0] = Math.Cos(angle);
                        ret.m[1, 0] = Math.Sin(angle);
                        ret.m[0, 1] = -Math.Sin(angle);
                        ret.m[1, 1] = Math.Cos(angle);
                        break;
                    case "xslant":
                        if (to.numval == null)
                            return false;
                        double amount = to.numval.GetInCM();
                        ret.m[0, 0] = 1;
                        ret.m[1, 0] = 0;
                        ret.m[0, 1] = amount;
                        ret.m[1, 1] = 1;
                        break;
                    case "yslant":
                        if (to.numval == null)
                            return false;
                        amount = to.numval.GetInCM();
                        ret.m[0, 0] = 1;
                        ret.m[1, 0] = amount;
                        ret.m[0, 1] = 0;
                        ret.m[1, 1] = 1;
                        break;
                    default:
                        // option not relevant for coordinate computation (or not supported) -> ignore
                        newTrafo = oldTrafo;
                        return true;
                }
            }
            // if we get here, the option was recognized as relevant for coordinate transf., and the value could be read
            newTrafo = oldTrafo * ret;
            return true;
        }
        //public List<Tikz_Option> options = new List<Tikz_Option>();

       // public static Tikz_Options FromCommonTree(CommonTree t)
       // {
            // IM_NODE OPTIONS? nodename? coord? STRING
       //     Tikz_Options opts = new Tikz_Options();
       //     foreach (CommonTree tt in t.Children)
       //     {
       //         Tikz_Option to = Tikz_Option.FromCommonTree(tt);
       //         if (to != null)
       //             opts.options.Add(to);
       //     }

       //     return opts;
       // }
    /*    public static TikzMatrix GetTransform(TikzContainerParseItem tcpi)
        {
            TikzMatrix ret = new TikzMatrix();

            double scale = 1, xshift = 0, yshift = 0;

            Tikz_Option o = GetOption(tcpi, "xshift", Tikz_OptionType.keyval);
            if (o != null)
                if (o.numval != null)
                    xshift = o.numval.GetInCM();
            o = GetOption(tcpi, "yshift", Tikz_OptionType.keyval);
            if (o != null)
                if (o.numval != null)
                    yshift = o.numval.GetInCM();
            o = GetOption(tcpi, "scale", Tikz_OptionType.keyval);
            if (o != null)
                if (o.numval != null)
                    scale = o.numval.GetInCM();
            ret.m[0, 0] = scale;
            ret.m[1, 1] = scale;
            ret.m[0, 2] = xshift;
            ret.m[1, 2] = yshift;
            return ret;
        } */

        /// <summary>
        /// Gets the total coordinate transformation that is encoded in this options block.
        /// How this apparently works in Tikz is as follows: 
        /// (determined by trial and error rather than specification, so hope for the best...)
        ///     - for each relevant option (shift, xshift, yshift, scale, xscale, yscale) a separate transformation is produced
        ///     - all those transformations are multiplied
        /// </summary>
        /// <returns></returns>
        public bool GetTransform(out TikzMatrix ret)
        {
            ret = new TikzMatrix();  // start with unit matrix
            foreach (TikzParseItem tpi in Children)
            {
                if (tpi is Tikz_Option)
                {
                    Tikz_Option to = tpi as Tikz_Option;
                    if (!TransformFromOption(to, ret, out ret))
                        return false;
                }
            }
            return true;
            /*
            double scale=1, xshift=0, yshift=0, xscale=1, yscale=1;

            Tikz_Option o = GetOption("xshift", Tikz_OptionType.keyval);
            if (o != null)
                if (o.numval != null)
                    xshift = o.numval.GetInCM("pt");
            o = GetOption("yshift", Tikz_OptionType.keyval);
            if (o != null)
                if (o.numval != null)
                    yshift = o.numval.GetInCM("pt");
            o = GetOption("scale", Tikz_OptionType.keyval);
            if (o != null)
                if (o.numval != null)
                   scale = o.numval.GetInCM();
            o = GetOption("xscale", Tikz_OptionType.keyval);
            if (o != null)
                if (o.numval != null)
                    xscale = o.numval.GetInCM();
            o = GetOption("yscale", Tikz_OptionType.keyval);
            if (o != null)
                if (o.numval != null)
                    yscale = o.numval.GetInCM();
            ret.m[0, 0] = scale * xscale;
            ret.m[1, 1] = scale * yscale;
            ret.m[0, 2] = xshift;
            ret.m[1, 2] = yshift; */
            //return ret;
        }
 /// <summary>
 /// This method determines the coord transform that should be used for rasterizing the scope's
 /// shift. Note that this is tricky since a scope per se does not have an anchor point.
 /// We take here as anchor point (i.e., the image of (0,0) under returned coord transformation)
 /// the transformed origin of the coordinate system at the position of the editable option shift=...
 /// that determines the scope's position.
 /// </summary>
 /// <param name="ret"></param>
 /// <returns></returns>
  public bool GetRasterTransform(out TikzMatrix ret)
  {
      if (options != null)
          return options.GetTransformAtEditableShift(out ret);
      else
          return parent.GetCurrentTransformAt(this, out ret);
  }
Exemple #10
0
      /*  public TikzMatrix GetCurrentTransform()
        {
            TikzMatrix M;
            //M = Tikz_Options.GetTransform(this);
            if (options != null)
                M = options.GetTransform();
            else
                M = new TikzMatrix();
            if (parent != null)
                M = parent.GetCurrentTransform() * M;
            return M;
        } */
        /// <summary>
        /// Determines the coordinate transformation at object childtpi,
        /// or at the end of the container in case childtpi is null.
        /// </summary>
        /// <param name="childtpi">The object to determine coordinate trsf. at.</param>
        /// <returns>The coordinate transformation.</returns>
        public bool GetCurrentTransformAt(TikzParseItem childtpi, out TikzMatrix M)
        {
            if (parent != null)
            {
                if (!parent.GetCurrentTransformAt(this, out M))
                    return false;
            }
            else
                M = new TikzMatrix(); // identity matrix

            foreach (TikzParseItem tpi in Children)
            {
                if (tpi == childtpi && childtpi != null)
                {
                    break;
                }
                else if (tpi is Tikz_Options)
                {
                    TikzMatrix MM;
                    if ((tpi as Tikz_Options).GetTransform(out MM))
                        M = M * MM;
                    else
                        return false;
                }
            }
            return true;
        }
        public void SetCorrectRaster(TikzParseItem tpi, bool IsParent = false)
        {
            if (ParseTree == null)
                return;
            if (tpi == null)
            {
                Tikz_Picture tp = ParseTree.GetTikzPicture();
                if (tp != null)
                {
                    TikzMatrix M;
                    if (!tp.GetCurrentTransformAt(null, out M))
                        Rasterizer.View.CoordinateTransform = new TikzMatrix();   // if the program gets here, the global coord. transformation could not be understood->ovelay should display nothing
                    else
                        Rasterizer.View.CoordinateTransform = M;
                    //rasterizer.RasterOrigin = M.Transform(new Point(0, 0));
                    //rasterizer.RasterScale = M.m[1, 1];
                    Rasterizer.View.IsCartesian = !UsePolarCoordinates;
                }
            }
            else if (tpi is Tikz_Scope)
            {
                Tikz_Scope ts = tpi as Tikz_Scope;
                TikzMatrix M;
                if (IsParent)
                {
                    if (!ts.GetCurrentTransformAt(null, out M))  // todo
                        M = new TikzMatrix(); // broken coords-> take unity as backup
                }
                else
                {
                    //if (!ts.parent.GetCurrentTransformAt(ts, out M))
                    //    M = new TikzMatrix();
                    if (!ts.GetRasterTransform(out M))
                        M = new TikzMatrix();
                }
                Rasterizer.View.CoordinateTransform = M;
                //rasterizer.RasterOrigin = M.Transform(new Point(0, 0));
                //rasterizer.RasterScale = M.m[1, 1];
                Rasterizer.View.IsCartesian = !IsParent || !UsePolarCoordinates;
            }
            else if (tpi is Tikz_XYItem)
            {
                Tikz_XYItem t = tpi as Tikz_XYItem;
                Point offset;
                if (t.GetAbsPos(out offset, true))
                {
                    TikzMatrix M;
                    if (!t.parent.GetCurrentTransformAt(t, out M)) //.CloneIt();
                        M = new TikzMatrix();

                    M.m[0, 2] = offset.X;
                    M.m[1, 2] = offset.Y;
                    //rasterizer.RasterScale = M.m[1, 1];
                    Rasterizer.View.CoordinateTransform = M;
                    Rasterizer.View.IsCartesian = !(t.IsPolar());
                }
                else throw new Exception("In PdfOverlay: Encountered drawn item without valid coordinates");
            }
            else if (tpi is Tikz_Path)
            {
                Tikz_Path ts = tpi as Tikz_Path;
                TikzMatrix M;
                if (IsParent)
                {
                    Point curPointAtEnd;
                    if (!ts.GetCurrentTransformAt(null, out M))  // todo
                        M = new TikzMatrix(); // broken coords-> take unity as backup
                    if (ts.GetAbsOffset(out curPointAtEnd, null))
                    {
                        M.m[0, 2] = curPointAtEnd.X;
                        M.m[1, 2] = curPointAtEnd.Y;
                    }
                }
                else
                {
                    if (!ts.parent.GetCurrentTransformAt(ts, out M))
                        M = new TikzMatrix();
                    //if (!ts.GetRasterTransform(out M))
                    //    M = new TikzMatrix();
                }
                Rasterizer.View.CoordinateTransform = M;
                //rasterizer.RasterOrigin = M.Transform(new Point(0, 0));
                //rasterizer.RasterScale = M.m[1, 1];
                Rasterizer.View.IsCartesian = !IsParent || !UsePolarCoordinates;
            }
            else
                Debug.WriteLine("Error in SetCorrectRaster: unsupported type");//Rasterizer.IsCartesian = true;  // should not get here
        }