Author Topic: Hatches scale display in MPolygon  (Read 5435 times)

0 Members and 1 Guest are viewing this topic.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Hatches scale display in MPolygon
« on: June 14, 2009, 10:29:46 AM »
Hi,

I'm trying to write a command for vanilla acad to convert objects (polylines, 2d polylines, circles) into a MPolygon.
It seems to work, the MPolygon is created with the specified pattern scale but it displays as if the scale was 1.0 even if in the properties palette the scale is as specified.

Add AcMPolygonMGD.dll to References
Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace VanillaMPolygon
{
    public class MpgClass : IExtensionApplication
    {
        public void Initialize()
        {
            string ver = Application.GetSystemVariable("ACADVER").ToString().Substring(0, 2);
            Autodesk.AutoCAD.Runtime.SystemObjects.DynamicLinker.LoadModule("AcMPolygonObj" + ver + ".dbx", false, false);
        }

        public void Terminate()
        {
        }

        [CommandMethod("PL2MPG")]
        public void PL2MPG()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            try
            {
                Database db = HostApplicationServices.WorkingDatabase;
                TypedValue[] filter = { new TypedValue(-4, "<or"),
                                           new TypedValue(0, "CIRCLE"),
                                           new TypedValue(-4, "<and"),
                                           new TypedValue(0, "LWPOLYLINE"),
                                           new TypedValue(-4, "&"),
                                           new TypedValue(70, 1),
                                           new TypedValue(-4, "and>"),
                                           new TypedValue(-4, "<and"),
                                           new TypedValue(0, "POLYLINE"),
                                           new TypedValue(-4, "&"),
                                           new TypedValue(70, 1),
                                           new TypedValue(-4, "<not"),
                                           new TypedValue(-4, "&"),
                                           new TypedValue(70, 120),
                                           new TypedValue(-4, "not>"),
                                           new TypedValue(-4, "and>"),
                                           new TypedValue(-4, "or>"),
                                       };
                SelectionFilter selFilter = new SelectionFilter(filter);
                PromptSelectionResult result = ed.GetSelection(selFilter);
                if (result.Status == PromptStatus.OK)
                {
                    ObjectId[] selSet = result.Value.GetObjectIds();
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                        BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                        MPolygon mPolygon = new MPolygon();

                        PromptStringOptions pso = new PromptStringOptions("\nEnter the hatch pattern name or a dot (.) for none: ");
                        pso.AllowSpaces = false;
                        pso.DefaultValue = (string)Application.GetSystemVariable("HPNAME");
                        PromptResult psr = ed.GetString(pso);
                        if (psr.Status != PromptStatus.OK)
                            return;
                        string pat = psr.StringResult.ToUpper();
                        if (pat != ".")
                        {
                            try
                            {
                                Application.SetSystemVariable("HPNAME", pat);
                                mPolygon.SetPattern(HatchPatternType.PreDefined, pat);
                                if ((pat != "SOLID") && (pat != "_SOLID"))
                                {
                                    PromptDoubleOptions pdo = new PromptDoubleOptions("\nSpecify the scale: ");
                                    pdo.AllowNegative = false;
                                    pdo.AllowZero = false;
                                    pdo.AllowNone = true;
                                    pdo.DefaultValue = (double)Application.GetSystemVariable("HPSCALE");
                                    PromptDoubleResult pdr = ed.GetDouble(pdo);
                                    if (pdr.Status != PromptStatus.OK)
                                        return;
                                    double scale = pdr.Value;
                                    mPolygon.PatternScale = scale;
                                    Application.SetSystemVariable("HPSCALE", scale);
                                }
                            }
                            catch
                            {
                                ed.WriteMessage("\nInvalid pattern: " + pat);
                                return;
                            }
                        }

                        foreach (ObjectId objId in selSet)
                        {
                            Entity ent = (Entity)tr.GetObject(objId, OpenMode.ForRead);
                            if (ent is Polyline)
                                mPolygon.AppendLoopFromBoundary((Polyline)ent, true, 1E-9);
                            else if (ent is Circle)
                                mPolygon.AppendLoopFromBoundary((Circle)ent, true, 1E-9);
                            else
                                mPolygon.AppendLoopFromBoundary((Polyline2d)ent, true, 1E-9);
                        }

                        PromptKeywordOptions pko = new PromptKeywordOptions("\nDelete source objects ? [Yes/No]: ", "Yes No");
                        pko.AllowNone = true;
                        pko.Keywords.Default = "No";
                        psr = ed.GetKeywords(pko);
                        if (psr.Status != PromptStatus.OK)
                            return;
                        if (psr.StringResult == "Yes")
                            foreach (ObjectId obj in selSet)
                            {
                                Entity ent = (Entity)tr.GetObject(obj, OpenMode.ForWrite);
                                ent.Erase();
                            }

                        mPolygon.BalanceTree();
                        if (mPolygon.PatternName != "") mPolygon.EvaluateHatch(true);
                        btr.AppendEntity(mPolygon);
                        tr.AddNewlyCreatedDBObject(mPolygon, true);
                        tr.Commit();
                    }
                }
            }

            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                ed.WriteMessage("Error: " + ex.Message);
            }

            catch (System.Exception ex)
            {
                ed.WriteMessage("Error: " + ex.Message);
            }
        }
    }
}
« Last Edit: June 14, 2009, 05:44:20 PM by gile »
Speaking English as a French Frog

ReneRam

  • Guest
Re: Hatches scale display in MPolygon
« Reply #1 on: June 15, 2009, 03:56:09 AM »
Hi gile,
I was just having a fast look at TheSwamp, but I think this could help:

http://www.theswamp.org/index.php?topic=20832.msg253549#msg253549

I had a problem while creating and displaying hatch patterns some time ago and gotthe solution here. Take a look at the code sent by "fixo", specially where it says that the order of creating and updating hatch patterns must be kept with the "SetHatchPattern(hatchType, patName)" at the end. I do it when creating and updating.


gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Hatches scale display in MPolygon
« Reply #2 on: June 15, 2009, 04:45:36 AM »
Thank you very much Rene (and thanks to Fixo too) this solved my problem.

Edit : new release

Code: [Select]
using System.Windows.Forms;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace VanillaMPolygon
{
    public class MpgClass : IExtensionApplication
    {
        void IExtensionApplication.Initialize()
        {
            string ver = AcApp.GetSystemVariable("ACADVER").ToString().Substring(0, 2);
            Autodesk.AutoCAD.Runtime.SystemObjects.DynamicLinker.LoadModule("AcMPolygonObj" + ver + ".dbx", false, false);
        }

        void IExtensionApplication.Terminate()
        {
        }

                [CommandMethod("PL2MPG")]
        public void PL2MPG()
        {
            Editor ed = AcApp.DocumentManager.MdiActiveDocument.Editor;
            try
            {
                Database db = HostApplicationServices.WorkingDatabase;

                TypedValue[] filter = { new TypedValue(-4, "<or"),
                                           new TypedValue(0, "CIRCLE"),
                                           new TypedValue(-4, "<and"),
                                           new TypedValue(0, "LWPOLYLINE"),
                                           new TypedValue(-4, "&"),
                                           new TypedValue(70, 1),
                                           new TypedValue(-4, "and>"),
                                           new TypedValue(-4, "<and"),
                                           new TypedValue(0, "POLYLINE"),
                                           new TypedValue(-4, "&"),
                                           new TypedValue(70, 1),
                                           new TypedValue(-4, "<not"),
                                           new TypedValue(-4, "&"),
                                           new TypedValue(70, 120),
                                           new TypedValue(-4, "not>"),
                                           new TypedValue(-4, "and>"),
                                           new TypedValue(-4, "or>"),
                                       };
                SelectionFilter selFilter = new SelectionFilter(filter);
                PromptSelectionResult result = ed.GetSelection(selFilter);

                if (result.Status != PromptStatus.OK)
                    return;

                ObjectId[] selSet = result.Value.GetObjectIds();
                double elev;
                Vector3d norm;
                if (!isValidSelSet(selSet, out elev, out norm))
                    return;

                double scale = (double)AcApp.GetSystemVariable("HPSCALE");
                PromptStringOptions pso = new PromptStringOptions("\nEnter the pattern name or a dot (.) for none: ");
                pso.AllowSpaces = false;
                pso.DefaultValue = (string)AcApp.GetSystemVariable("HPNAME");
                PromptResult psr = ed.GetString(pso);
                if (psr.Status != PromptStatus.OK)
                    return;
                string pat = psr.StringResult.ToUpper();

                 if (pat != ".")
                {
                    try
                    {
                        AcApp.SetSystemVariable("HPNAME", pat);

                        if ((pat != "SOLID") && (pat != "_SOLID"))
                        {
                            PromptDoubleOptions pdo = new PromptDoubleOptions("\nEnter the pattern scale: ");
                            pdo.AllowNegative = false;
                            pdo.AllowZero = false;
                            pdo.AllowNone = true;
                            pdo.DefaultValue = scale;
                            PromptDoubleResult pdr = ed.GetDouble(pdo);
                            if (pdr.Status != PromptStatus.OK)
                                return;
                            scale = pdr.Value;
                            AcApp.SetSystemVariable("HPSCALE", scale);
                        }
                    }
                    catch
                    {
                        ed.WriteMessage("\nInvalid pattern: " + pat);
                        pat = ".";
                        return;
                    }
                }

                PromptKeywordOptions pko = new PromptKeywordOptions("\nErase source objects ? [Yes/No]: ", "Yes No");
                pko.AllowNone = true;
                pko.Keywords.Default = "No";
                psr = ed.GetKeywords(pko);
                if (psr.Status != PromptStatus.OK)
                    return;

                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                    MPolygon mPolygon = new MPolygon();
                    Entity ent;

                    btr.AppendEntity(mPolygon);
                    tr.AddNewlyCreatedDBObject(mPolygon, true);

                    mPolygon.UpgradeOpen();
                    mPolygon.PatternScale = scale;
                    if (pat != ".")
                        mPolygon.SetPattern(HatchPatternType.PreDefined, pat);
                    mPolygon.DowngradeOpen();

                    foreach (ObjectId objId in selSet)
                    {
                        ent = (Entity)objId.GetObject(OpenMode.ForRead);
                        if (ent is Polyline)
                            mPolygon.AppendLoopFromBoundary((Polyline)ent, true, 1E-12);
                        else if (ent is Circle)
                            mPolygon.AppendLoopFromBoundary((Circle)ent, true, 1E-12);
                        else
                            mPolygon.AppendLoopFromBoundary((Polyline2d)ent, true, 1E-12);
                    }

                    mPolygon.BalanceTree();

                    mPolygon.Elevation = elev;
                    mPolygon.Normal = norm;

                    if (mPolygon.PatternName != "") mPolygon.EvaluateHatch(true);

                    int cnt = 0;
                    if (psr.StringResult == "Yes")
                        foreach (ObjectId obj in selSet)
                        {
                            try
                            {
                                ent = (Entity)obj.GetObject(OpenMode.ForWrite);
                                ent.Erase();
                            }
                            catch
                            {
                                cnt++;
                            }
                        }
                    if (0 < cnt)
                    {
                        string msg = cnt == 1 ?
                            " object on locked layer will not be erased" :
                            " objects on locked layer will not be erased";
                        MessageBox.Show(
                            cnt.ToString() + msg,
                            "PL2MPG",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Exclamation);
                    }

                     tr.Commit();
                }
            }

            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                ed.WriteMessage("Error: " + ex.Message);
            }

            catch (System.Exception ex)
            {
                ed.WriteMessage("Error: " + ex.Message);
            }
        }


        private bool isValidSelSet(ObjectId[] selSet, out double elev, out Vector3d norm)
        {
            Editor ed = AcApp.DocumentManager.MdiActiveDocument.Editor;
            Database db = HostApplicationServices.WorkingDatabase;
            Polyline pl;
            Circle circ;
            Polyline2d p2d;
            Tolerance tol = new Tolerance(1E-12, 1E-12);

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                Entity ent = (Entity)selSet[0].GetObject(OpenMode.ForRead);
                pl = ent as Polyline;
                if (pl != null)
                {
                    elev = pl.Elevation;
                    norm = pl.Normal;
                }
                else
                {
                    circ = ent as Circle;
                    if (circ != null)
                    {
                        elev = circ.Center.TransformBy(Matrix3d.WorldToPlane(circ.Normal)).Z;
                        norm = circ.Normal;
                    }
                    else
                    {
                        p2d = ent as Polyline2d;
                        elev = p2d.Elevation;
                        norm = p2d.Normal;
                    }
                }

                for (int i = 1; i < selSet.Length; i++)
                {
                    ent = (Entity)selSet[i].GetObject(OpenMode.ForRead);
                    pl = ent as Polyline;
                    if (pl != null)
                    {
                        if ((elev - pl.Elevation) > 1E-12)
                        {
                            ed.WriteMessage("\nThe objects doesn't have the same elevation.");
                            tr.Commit();
                            return false;
                        }
                        else if (!norm.IsEqualTo(pl.Normal, tol))
                        {
                            ed.WriteMessage("\nThe objects doesn't have the same normal.");
                            tr.Commit();
                            return false;
                        }
                    }
                    else
                    {
                        circ = ent as Circle;
                        if (circ != null)
                        {
                            if ((elev - circ.Center.TransformBy(Matrix3d.WorldToPlane(circ.Normal)).Z) > 1E-12)
                            {
                                ed.WriteMessage("\nThe objects doesn't have the same elevation..");
                                tr.Commit();
                                return false;
                            }
                            else if (!norm.IsEqualTo(circ.Normal, tol))
                            {
                                ed.WriteMessage("\nThe objects doesn't have the same normal.");
                                tr.Commit();
                                return false;
                            }
                        }
                        else
                        {
                            p2d = ent as Polyline2d;
                            if ((elev - p2d.Elevation) > 1e-12)
                            {
                                ed.WriteMessage("\nThe objects doesn't have the same elevation.");
                                tr.Commit();
                                return false;
                            }
                            else if (!norm.IsEqualTo(p2d.Normal, tol))
                            {
                                ed.WriteMessage("\nThe objects doesn't have the same normal.");
                                tr.Commit();
                                return false;
                            }
                        }
                    }
                }
                tr.Commit();
                return true;
            }
        }
    }
}
« Last Edit: June 16, 2009, 06:06:22 PM by gile »
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Hatches scale display in MPolygon
« Reply #3 on: June 16, 2009, 06:09:55 PM »
Hi,

New version: added a function to evaluate if selected objects have the same elevation and normal.
It works whatever the source objects construction plane (just need to be the same for all objects)
« Last Edit: June 17, 2009, 02:24:56 AM by gile »
Speaking English as a French Frog

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Hatches scale display in MPolygon
« Reply #4 on: July 24, 2009, 04:33:45 PM »
gile I have used your filter list to filter for hatchable items but I would like to add a filter for elliptic arcs. I can't figure out quite how to do it. the following doesn't work when you uncomment the applicable lines
Code: [Select]
    static private SelectionFilter HatchFilterlist()
        {
            TypedValue[] filterlist = {
                new TypedValue(-4, "<or"),
                new TypedValue(0, "Circle,Spline,Region"),
                new TypedValue(-4, "<and"),
                new TypedValue(0, "Lwpolyline"),
                new TypedValue(-4, "&"),
                new TypedValue(70,1),
                new TypedValue(-4, "and>"),
                new TypedValue(-4, "<and"),
                new TypedValue(0, "Ellipse"),
                //new TypedValue(-4, "&"),
                //new TypedValue(41,0.00),
                //new TypedValue(-4, "&"),
                //new TypedValue(42,2*Math.PI),
                new TypedValue(-4, "and>"),
                new TypedValue(-4, "or>"),};
            SelectionFilter sf = new SelectionFilter(filterlist);
            return sf;
        }

SEANT

  • Bull Frog
  • Posts: 345
Re: Hatches scale display in MPolygon
« Reply #5 on: July 26, 2009, 03:27:13 AM »
gile I have used your filter list to filter for hatchable items but I would like to add a filter for elliptic arcs. I can't figure out quite how to do it. the following doesn't work when you uncomment the applicable lines

The bitwise operator “&” is only compatible with integers.  If that’s left out will it filter as expected?

Code: [Select]
                new TypedValue(0, "Ellipse"),
                [color=green]//new TypedValue(-4, "&"),[/color]
                new TypedValue(41,0.00),
                [color=green]//new TypedValue(-4, "&"),[/color]
                new TypedValue(42,2*Math.PI),
                new TypedValue(-4, "and>"),
Sean Tessier
AutoCAD 2016 Mechanical

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Hatches scale display in MPolygon
« Reply #6 on: July 27, 2009, 12:23:45 PM »
Thanks Sean that did the trick. I eventually found the help on this in Lisp (never use it)
Code: [Select]
static private SelectionFilter HatchFilterlist()
        {
            TypedValue[] filterlist = {
                new TypedValue(-4, "<or"),
                new TypedValue(0, "Circle,Region"),
                new TypedValue(-4, "<and"),
                new TypedValue(0, "Lwpolyline,Spline"),
                new TypedValue(-4, "&"),
                new TypedValue(70,1),
                new TypedValue(-4, "and>"),
                new TypedValue(-4, "<and"),
                new TypedValue(0, "Ellipse"),
                new TypedValue(41,0.00),
                new TypedValue(42,2*Math.PI),
                new TypedValue(-4, "and>"),
                new TypedValue(-4, "or>"),};
            SelectionFilter sf = new SelectionFilter(filterlist);
            return sf;
        }//End HatchFilterlist

It's odd that I even have to use new TypedValue(-4, "&") in the above, but it doesn't work for plines and splines without it

SEANT

  • Bull Frog
  • Posts: 345
Re: Hatches scale display in MPolygon
« Reply #7 on: July 27, 2009, 01:36:15 PM »
I think the problem is that “Closed” is bitcoded with other properties which may not have relevance to a particular routine, but prevent a focused search for a value of 1.

In that light, and given that the routine will eventually create hatches, the spline filter may also need to account for the non-planar variety.  I haven’t tested it but:

Code: [Select]
new TypedValue(0, "Spline"),
new TypedValue(-4, "&="),
new TypedValue(70,9),
Sean Tessier
AutoCAD 2016 Mechanical