Author Topic: Draw rectangles at regular interval on Polyline, Badly need in help...  (Read 9886 times)

0 Members and 1 Guest are viewing this topic.

sachinpise

  • Guest
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #15 on: December 22, 2010, 12:28:51 AM »
Hello Kerry, Kaefer

I am really stuck with following code. I have a method which tells me weather the rectangles should be drawn on left side or right side. But I am not able to get the left/ right direction correct. Please see the following code, I am sure I have messed it out...


Code: [Select]
for (int i = 0; i < pointList.Count; i++)
                {
                    Point3d point1 = pointList[i];
                    Vector3d vector = vec3D.DivideBy(vec3D.Length);
                    vector = vector.MultiplyBy(width);
                    Point3d point2 = point1 + vector;
                    vector = drawOnLeft.Value ? (point1 - point2).GetPerpendicularVector().MultiplyBy(length) : (point2 - point1).GetPerpendicularVector().MultiplyBy(length);
                    Point3d point3 = point2 + vector;
                    Point3d point4 = point1 + vector;
                    if (!PolylineManager.PointInsidePoly(point3, slabPolyline.ObjectId))
                        continue;
                    if (!PolylineManager.PointInsidePoly(point4, slabPolyline.ObjectId))
                        continue;
                    Autodesk.AutoCAD.DatabaseServices.Polyline polyline = new Autodesk.AutoCAD.DatabaseServices.Polyline();
                    polyline.AddVertexAt(polyline.NumberOfVertices, new Point2d(point1.X, point1.Y), 0, 0, 0);
                    polyline.AddVertexAt(polyline.NumberOfVertices, new Point2d(point2.X, point2.Y), 0, 0, 0);
                    polyline.AddVertexAt(polyline.NumberOfVertices, new Point2d(point3.X, point3.Y), 0, 0, 0);
                    polyline.AddVertexAt(polyline.NumberOfVertices, new Point2d(point4.X, point4.Y), 0, 0, 0);
                    polyline.Closed = true;
                    polylineList.Add(polyline);
                }

I tried both following ways with no expected result.


Code: [Select]
vector = drawOnLeft.Value ? (point1 - point2).GetPerpendicularVector().MultiplyBy(length) : (point2 - point1).GetPerpendicularVector().MultiplyBy(length);


Code: [Select]
vector = (point2 - point1).GetPerpendicularVector().MultiplyBy(drawOnLeft.Value ? length : -length);


kaefer

  • Guest
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #16 on: December 22, 2010, 06:59:12 AM »


I can't really understand why you would have trouble with this. You aren't telling us the whole truth, perhaps?

Quote
Code: [Select]
vector = drawOnLeft.Value ? (point1 - point2).GetPerpendicularVector().MultiplyBy(length) : (point2 - point1).GetPerpendicularVector().MultiplyBy(length);

Code: [Select]
vector = (point2 - point1).GetPerpendicularVector().MultiplyBy(drawOnLeft.Value ? length : -length);

These two look pretty equivalent. If you'd like yet another way to come to the very same result, see the definition of PolarPoint e.g. here http://www.theswamp.org/index.php?topic=31861.msg386487#msg386487. Determine the angle of point2 - point1 and call PolarPoint with PI / 2. added to the angle.

That should not be surprising given the operation of Vector3d.GetPerpendicularVector(), which returns a normalized new Vector(-y, x, z) .

Cheers
« Last Edit: December 22, 2010, 09:25:04 AM by kaefer »

sachinpise

  • Guest
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #17 on: December 22, 2010, 08:53:38 AM »
Hi Kaefer

No luck in understanding what you meant... I tried some options with big exceptions.

Regards,
Sachin

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #18 on: December 22, 2010, 09:36:03 AM »

How about s0mething like this. ??

Code to follow.
The code needs some pruning, but it's past my bedtime.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

kaefer

  • Guest
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #19 on: December 22, 2010, 09:48:02 AM »
No luck in understanding what you meant... I tried some options with big exceptions.

See, the side your little boxes are on is dependent on the order of your two base points, i.e the direction of your polyline. Now, in the absence of any corrective action this will be the left hand side of your polyline, as if you'd have rotated them by 90 degrees counterclockwise.

You seem to apply that correction by means of your drawOnLeft.Value, so any possible error must have occured before that. That's why I'm unable to see anything untoward with your code fragment.

All the best

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #20 on: December 22, 2010, 09:57:03 AM »

Code: [Select]

// (C) CodeHimBelonga kdub@theSwamp 2010
//
using System;
using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly: CommandClass(typeof(kdub_Testing.LittleBoxes))]

namespace kdub_Testing
{
    public class LittleBoxes
    {
        Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
        Database db = HostApplicationServices.WorkingDatabase;

        [CommandMethod("HACK3")]
        public void HACK3()
        {
            double spacing = 200.0;
            double length = 400.0;
            double width = 50.0;
            Point3d ptStart = new Point3d();
            Point3d ptEnd = new Point3d();

            //-1 if ptSide is on left side
            //+1 if ptSide is on right side
            int hackSide = 0;

            bool proceed = GetUserInput(ref ptStart, ref ptEnd, ref hackSide);

            if(proceed == false) {
                System.Windows.Forms.MessageBox.Show("You Made Boo-Boo Selection",
                    "Oooops",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation
                    );
                return;
            }
            Vector3d v1 = (Vector3d)(ptEnd - ptStart);
            double wpLen = v1.Length;

            int spacingCount = (int)((wpLen / spacing) - 2);
            Vector3d spacingVector = v1.MultiplyBy(spacing / wpLen);
            Vector3d firstVec = v1.MultiplyBy(((wpLen - (spacingCount * spacing) - width) / 2) / wpLen);

            // draw first box
            // describe the PolyLine rectangle corners as vectors relative to the firstCorner
            //
            Vector3d xLen = v1.DivideBy(v1.Length).MultiplyBy(width);
            Vector3d yLen = v1.GetPerpendicularVector().MultiplyBy(-(hackSide * length));
            Point3d vertex0 = ptStart.Add(firstVec);
            Point3d vertex1 = vertex0 + yLen;
            Point3d vertex2 = vertex1 + xLen;
            Point3d vertex3 = vertex0 + xLen;


            using(Transaction tr = db.TransactionManager.StartTransaction()) {
                Polyline polyline = new Polyline();
                polyline.AddVertexAt(polyline.NumberOfVertices, new Point2d(vertex0.X, vertex0.Y), 0, 0, 0);
                polyline.AddVertexAt(polyline.NumberOfVertices, new Point2d(vertex1.X, vertex1.Y), 0, 0, 0);
                polyline.AddVertexAt(polyline.NumberOfVertices, new Point2d(vertex2.X, vertex2.Y), 0, 0, 0);
                polyline.AddVertexAt(polyline.NumberOfVertices, new Point2d(vertex3.X, vertex3.Y), 0, 0, 0);
                polyline.Closed = true;

                ObjectId plRectangle = ExtensionTools.AddToCurrentSpaceAndClose(polyline, db);
                ExtensionTools.ArrayInAxis(plRectangle, db, (spacingCount + 1), spacingVector);
                tr.Commit();
            }
        }
    }
}

Code: [Select]
        public bool GetUserInput(ref Point3d ptStart, ref Point3d ptEnd, ref int hackSide)
        {
// (C) CodeHimBelonga kdub@theSwamp 2010
//
            PromptPointResult ppr;
            PromptPointOptions ppo = new PromptPointOptions("");

            PromptEntityOptions peo = new PromptEntityOptions("\nSelect a PolyLine segment, or[Points]", "Points");
            peo.AllowNone = true;
            peo.SetRejectMessage("\nIncorrect entity");
            peo.AddAllowedClass(typeof(Polyline), true);
            peo.Keywords.Default = "Points";
            PromptEntityResult per = ed.GetEntity(peo);
            switch(per.Status) {
                case PromptStatus.Cancel:
                    return false;
                case PromptStatus.OK:
                    Point3d p0;
                    Point3d p1;
                    using(Transaction tr = db.TransactionManager.StartTransaction()) {
                        Polyline pline = (Polyline)tr.GetObject(per.ObjectId, OpenMode.ForRead);
                        Point3d pickPt = pickPointOnPline(pline, per.PickedPoint);
                        double param = pline.GetParameterAtPoint(pickPt);
                        int index = (int)param;
                        p0 = pline.GetPoint3dAt(index);

                        if(pline.Closed == false)
                            p1 = pline.GetPoint3dAt(index + 1);
                        else {
                            try { p1 = pline.GetPoint3dAt(index + 1); } catch { p1 = pline.GetPoint3dAt(0); }
                        }

                        if(pickPt.DistanceTo(p0) <= pickPt.DistanceTo(p1)) {
                            ptStart = p0;
                            ptEnd = p1;
                        } else {
                            ptStart = p1;
                            ptEnd = p0;
                        }
                        tr.Commit();
                    }

                    break;
                case PromptStatus.Keyword:
                    switch(per.StringResult) {
                        case "Points":
                            // Prompt for the start point
                            ppo.Message = "\nEnter the start point of the line: ";
                            ppr = ed.GetPoint(ppo);
                            ptStart = ppr.Value;

                            // Exit if the user presses ESC or cancels the command
                            if(ppr.Status == PromptStatus.Cancel)
                                return false;

                            // Prompt for the end point
                            ppo.Message = "\nEnter the end point of the line: ";
                            ppo.UseBasePoint = true;
                            ppo.BasePoint = ptStart;
                            ppr = ed.GetPoint(ppo);
                            ptEnd = ppr.Value;

                            if(ppr.Status == PromptStatus.Cancel)
                                return false;
                            break;

                        default:
                            return false;
                    }
                    break;
            }
            Matrix3d UCSMatrix = ed.CurrentUserCoordinateSystem;
            CoordinateSystem3d UCS = UCSMatrix.CoordinateSystem3d;
            Plane xyPlane = new Plane(ptStart, UCS.Xaxis, UCS.Yaxis);
            double angle0 = (ptEnd - ptStart).AngleOnPlane(xyPlane);

            Int16 osmode = (Int16)AcadApp.GetSystemVariable("OSMODE");
            double snapang = (double)AcadApp.GetSystemVariable("SNAPANG");
            AcadApp.SetSystemVariable("OSMODE", 1);
            AcadApp.SetSystemVariable("SNAPANG", angle0);

            Point3d ptSide = new Point3d();
            // Prompt for the HackSide           
            ppo.Message = "\nSelect the hack direction : ";
            ppo.UseBasePoint = true;
            ppo.BasePoint = ptStart;
            ppr = ed.GetPoint(ppo);
            ptSide = ppr.Value;

            AcadApp.SetSystemVariable("OSMODE", osmode);
            AcadApp.SetSystemVariable("SNAPANG", snapang);

            if(ppr.Status == PromptStatus.Cancel)
                return false;

            //-1 if ptSide is on left side
            //+1 if ptSide is on right side
            hackSide = ExtensionTools.DeflectionSide(ptStart, ptEnd, ptSide);

            return true;
        }

        // Credit to Gile @theSwamp
        private Point3d pickPointOnPline(Polyline pl, Point3d pt)
        {
            pt = pt.TransformBy(ed.CurrentUserCoordinateSystem);
            Vector3d vdir = ed.GetCurrentView().ViewDirection;
            pt = pt.Project(pl.GetPlane(), vdir);
            return pl.GetClosestPointTo(pt, false);
        }


ExtensionTools
Code: [Select]

// (C) CodeHimBelonga kdub@theSwamp 2010
//
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace kdub_Testing
{
    public static class ExtensionTools
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db"></param>
        /// <param name="numCols"></param>
        /// <param name="displacementVector"></param>
        public static void ArrayInAxis(this ObjectId id, Database db, int numCols, Vector3d displacementVector )
        {
            using(Transaction tr = db.TransactionManager.StartTransaction()) {
                BlockTable table = tr.GetObject(db.BlockTableId, OpenMode.ForRead, false) as BlockTable;
                BlockTableRecord record = tr.GetObject(table[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false) as BlockTableRecord;
                Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;

                for(int j = 0; j < numCols; j++) {
                    Matrix3d transform = Matrix3d.Displacement(new Vector3d(j * displacementVector.X, j * displacementVector.Y, j * displacementVector.Z));
                    Entity transformedCopy = ent.GetTransformedCopy(transform);
                    record.AppendEntity(transformedCopy);
                    tr.AddNewlyCreatedDBObject(transformedCopy, true);
                }
                ent.Erase();
                tr.Commit();
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="ent"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public static ObjectId AddToCurrentSpaceAndClose(Entity ent, Database db)
        {
            ObjectId objId;
            using(Transaction tr = db.TransactionManager.StartTransaction()) {
                objId = AddToCurrentSpace(ent, db, tr);
                tr.Commit();
            }
            return objId;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="ent"></param>
        /// <param name="db"></param>
        /// <param name="tr"></param>
        /// <returns></returns>
        public static ObjectId AddToCurrentSpace(Entity ent, Database db, Transaction tr)
        {
            ObjectId objId;
            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
            objId = btr.AppendEntity(ent);
            tr.AddNewlyCreatedDBObject(ent, true);
            return objId;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// Returns -1 if p3 is on left side of vector p1-p2,
        /// or returns +1 if p3 is on right side of vector p1-p2.
        /// Points are converted to XY plane.
        /// <returns></returns>
        public static int DeflectionSide(Point3d p1, Point3d p2, Point3d p3)
        {
            return DeflectionSide(
                new Point2d(p1.X, p1.Y),
                new Point2d(p2.X, p2.Y),
                new Point2d(p3.X, p3.Y)
                );
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// Returns -1 if p3 is on left side of vector p1-p2,
        /// or returns +1 if p3 is on right side of vector p1-p2.
        /// Points are converted to XY plane.
        /// <returns></returns>

        public static int DeflectionSide(Point2d p1, Point2d p2, Point2d p3)
        {           
            return (((p2.X - p1.X) * (p3.Y - p1.Y)) - ((p2.Y - p1.Y) * (p3.X - p1.X)) > 0) ? -1 : 1;
        }

    }
}


ANd the Project/Solution
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

sachinpise

  • Guest
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #21 on: December 23, 2010, 12:07:16 AM »
Hi Kerry

I really thank you very much for all the trouble you took to give me a complete project. It is nice and easy to understand. I really appreciate your help.
I have started to change my code and once I am successful with output I shall post here to let you know.

Thanks & Regards,
Sachin

kaefer

  • Guest
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #22 on: December 23, 2010, 05:06:08 AM »
Code: [Select]
// (C) CodeHimBelonga kdub@theSwamp 2010
...
    public class LittleBoxes
    {
        Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
        Database db = HostApplicationServices.WorkingDatabase;

        [CommandMethod("HACK3")]
        public void HACK3()
        {
        ...

Hi Kerry,

am I allowed to do a little critiquing?

Well done.

The implicit constructor technique above got me stumped at first, but I recognize their value, especially when these fields are made public for later consumption by additional modules.

Quote
Code: [Select]
                ...
                BlockTableRecord record = tr.GetObject(table[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false) as BlockTableRecord;
                Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;

                for(int j = 0; j < numCols; j++) {
                    Matrix3d transform = Matrix3d.Displacement(new Vector3d(j * displacementVector.X, j * displacementVector.Y, j * displacementVector.Z));
                    ...

Here the Modelspace is hardcoded, so HACK3 won't work in Paperspace.

The last line could surely be written as
Code: [Select]
                    Matrix3d transform = Matrix3d.Displacement(displacementVector.MultiplyBy(j));

Otherwise it's very difficult for me to localize possible further gnats in the ointment.

Take it easy, Thorsten

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #23 on: December 23, 2010, 05:12:43 AM »
Hi kaefer
Quote
am I allowed to do a little critiquing?
absolutely   :laugh: 


I appreciate the feedback.

Regarding Modelspace/paperspace ..
I can't think of any logical reason why anyone would want to do this sort of detailing in Paperspace.

Thankfully the issue is easily resolved by using 'CurrentSpace' if required. ... but good point :)

Quote
The last line could surely be written as
Code: [Select]
                   Matrix3d transform = Matrix3d.Displacement(displacementVector.MultiplyBy(j));

yes it could I think .. good eye !
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #24 on: December 23, 2010, 05:34:36 AM »
Sachin,

Regarding the distance to the first rectangle.
Are there cases where it must be a specific distance from the StartPoint ?

It's a little hard to know your process without understanding your product.
For instance, are the slabs solid or cored ?
If cored, is the knockout location related to the core location ?

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

sachinpise

  • Guest
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #25 on: December 23, 2010, 06:05:04 AM »
Hi Kerry

Actually yes, it starts at specific distance from the bottom or top. The cores are parallel to the Slabs. There are 2 kinds of hacking. One is on cores and other one is on side which is perpendicular to the cores or length of the slab. The core hacking, fortunately I was able to do it, because I used cores as base objects. But these ones were becoming difficult. These hackings are perpendicular to slab length. You can see the attached image and you will get the idea. The yellow boxes are the result of your help and the core lines are in light gray which are perpendicular to the these rectangles.

Note: To the rectangle I also add Hatch so you may not see the boxes clearly.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #26 on: December 23, 2010, 06:45:17 AM »


ok, be back in a bit ..
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Draw rectangles at regular interval on Polyline, Badly need in help...
« Reply #27 on: December 23, 2010, 06:50:11 AM »
Hack this into the  HACK3() method
Code: [Select]
//< .... snip  >
            if(proceed == false) {
                System.Windows.Forms.MessageBox.Show("You Made Boo-Boo Selection",
                    "Oooops",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation
                    );
                return;
            }
            Vector3d v1 = (Vector3d)(ptEnd - ptStart);
            double wpLen = v1.Length;

            // revised to marker - Prompt to confirm first space <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

            int spacingCount = (int)((wpLen / spacing) - 2);
            int firstDim = (int)((wpLen - (spacingCount * spacing) - width) / 2) ;

            PromptIntegerOptions pio = new PromptIntegerOptions("\nSpacing to CenterLine of First Hackout");
            pio.AllowNegative = false;
            pio.AllowZero = false;
            pio.AllowNone = false;
            pio.DefaultValue = firstDim + (int)(width * 0.5);
            PromptIntegerResult pir = ed.GetInteger(pio);
            if(pir.Status == PromptStatus.OK)
                firstDim = pir.Value - (int)(width * 0.5);

            spacingCount = (int)( ( ( wpLen - firstDim )  / spacing) - 1);

            pio = new PromptIntegerOptions("\nHackout quantum");
            pio.AllowNegative = false;
            pio.AllowZero = false;
            pio.AllowNone = false;
            pio.DefaultValue = (spacingCount + 1);

            pir = ed.GetInteger(pio);
            if(pir.Status == PromptStatus.OK)
                spacingCount = pir.Value - 1;

            Vector3d spacingVector = v1.MultiplyBy(spacing / wpLen);
            Vector3d firstVec = v1.MultiplyBy(firstDim / wpLen) ;
            
            //revised ^^^ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

            // draw first box
//< .... snip  >

« Last Edit: December 23, 2010, 07:08:42 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.