Hi,
My requirement is, I will select a polyline on drawing and enter some text, on OK click I have to move the text along the polyline. I am able to jig along polyline and place at selected point along the polyline. But my issue is, the text block rotation is not according to the polyline angle when moving along it. Could you please help me in this.
I used the below link for reference to jig along the polyline.
https://drive-cad-with-code.blogspot.com/2012/03/moving-entity-along-curve.html
Thanks in advance for your suggestions
Tejaswini.
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Solved by _gile. Go to Solution.
You should get some inspiration from this one.
[CommandMethod("JIGTEXT")] public static void JigTextAlonPpolyline() { var doc = Application.DocumentManager.MdiActiveDocument; var db = doc.Database; var ed = doc.Editor; var entityOptions = new PromptEntityOptions("\nSelect polyline: "); entityOptions.SetRejectMessage("\nmust be a Polyline."); entityOptions.AddAllowedClass(typeof(Polyline), true); var entityResult = ed.GetEntity(entityOptions); if (entityResult.Status != PromptStatus.OK) return; var stringOptions = new PromptStringOptions("\nEnter a text: "); stringOptions.AllowSpaces = true; var stringResult = ed.GetString(stringOptions); if (stringResult.Status != PromptStatus.OK) return; using (var tr = db.TransactionManager.StartTransaction()) { var pline = (Polyline)tr.GetObject(entityResult.ObjectId, OpenMode.ForRead); using (var text = new DBText()) { text.SetDatabaseDefaults(); text.Normal = pline.Normal; text.Justify = AttachmentPoint.BottomCenter; text.AlignmentPoint = Point3d.Origin; text.TextString = stringResult.StringResult; var jig = new TextJig(text, pline); var result = ed.Drag(jig); if (result.Status == PromptStatus.OK) { var currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); currentSpace.AppendEntity(text); tr.AddNewlyCreatedDBObject(text, true); } } tr.Commit(); } } class TextJig : EntityJig { DBText text; Polyline pline; Point3d dragPt; Plane plane; Database db; public TextJig(DBText text, Polyline pline) : base(text) { this.text = text; this.pline = pline; plane = new Plane(Point3d.Origin, pline.Normal); db = HostApplicationServices.WorkingDatabase; } protected override SamplerStatus Sampler(JigPrompts prompts) { var options = new JigPromptPointOptions("\nSpecicfy insertion point: "); options.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.UseBasePointElevation; var result = prompts.AcquirePoint(options); if (result.Value.IsEqualTo(dragPt)) return SamplerStatus.NoChange; dragPt = result.Value; return SamplerStatus.OK; } protected override bool Update() { var point = pline.GetClosestPointTo(dragPt, false); var angle = pline.GetFirstDerivative(point).AngleOnPlane(plane); text.AlignmentPoint = point; text.Rotation = angle; text.AdjustAlignment(db); return true; } }
Hi,
Thanks for your solution, But my requirement is moving a block having attribute value as text. I have to move my block along the selected polyline, aligning with angle of polyline. and the block should jig below the polyline, not above the polyline. And I have both the polyline and block entities present with me.
Please help me in this regard.
Thanks in advance.
Tejaswini.
This is NOT your first requirement.
In the first maeesage you said: "I will select a polyline on drawing and enter some text, on OK click I have to move the text along the polyline."
By respect to those who try to help you, please do not change the requirements in the same thread.
From the upper code and this one in another post of yours, you should be able to achieve what you want.
Try this.
[CommandMethod("JIGBLOCK")] public static void JigBlockAlongPolyline() { var doc = AcAp.DocumentManager.MdiActiveDocument; var db = doc.Database; var ed = doc.Editor; var entityOptions = new PromptEntityOptions("\nSelect polyline: "); entityOptions.SetRejectMessage("\nmust be a Polyline."); entityOptions.AddAllowedClass(typeof(Polyline), true); var entityResult = ed.GetEntity(entityOptions); if (entityResult.Status != PromptStatus.OK) return; var stringOptions = new PromptStringOptions("\nEnter the block name: "); var stringResult = ed.GetString(stringOptions); if (stringResult.Status != PromptStatus.OK) return; var blockName = stringResult.StringResult; using (var tr = db.TransactionManager.StartTransaction()) { var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); if (!bt.Has(blockName)) return; var pline = (Polyline)tr.GetObject(entityResult.ObjectId, OpenMode.ForRead); var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); var btrId = bt[blockName]; var br = new BlockReference(Point3d.Origin, btrId); curSpace.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); var btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead); var attInfos = new Dictionary<AttributeReference, TextInfo>(); foreach (ObjectId id in btr) { if (id.ObjectClass.Name == "AcDbAttributeDefinition") { var attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead); AttributeReference attRef = new AttributeReference(); attRef.SetAttributeFromBlock(attDef, br.BlockTransform); br.AttributeCollection.AppendAttribute(attRef); tr.AddNewlyCreatedDBObject(attRef, true); attInfos.Add(attRef, new TextInfo(attDef)); } } var jig = new BlockJig(br, pline, attInfos); var pr = ed.Drag(jig); if (pr.Status != PromptStatus.OK) br.Erase(); tr.Commit(); } } class TextInfo { public Point3d Position { get; } public Point3d Alignment { get; } public bool IsAligned { get; } public double Rotation { get; } public TextInfo(DBText text) { Position = text.Position; IsAligned = text.Justify != AttachmentPoint.BaseLeft; Alignment = text.AlignmentPoint; Rotation = text.Rotation; } } class BlockJig : EntityJig { BlockReference br; Polyline pline; Point3d dragPt; Plane plane; Dictionary<AttributeReference, TextInfo> attInfos; public BlockJig(BlockReference br, Polyline pline, Dictionary<AttributeReference, TextInfo> attInfos) : base(br) { this.br = br; this.pline = pline; this.attInfos = attInfos; plane = new Plane(Point3d.Origin, pline.Normal); } protected override SamplerStatus Sampler(JigPrompts prompts) { var options = new JigPromptPointOptions("\nSpecicfy insertion point: "); options.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.UseBasePointElevation; var result = prompts.AcquirePoint(options); if (result.Value.IsEqualTo(dragPt)) return SamplerStatus.NoChange; dragPt = result.Value; return SamplerStatus.OK; } protected override bool Update() { var point = pline.GetClosestPointTo(dragPt, false); var angle = pline.GetFirstDerivative(point).AngleOnPlane(plane); br.Position = point; br.Rotation = angle; foreach (var entry in attInfos) { var att = entry.Key; var info = entry.Value; att.Position = info.Position.TransformBy(br.BlockTransform); att.Rotation = info.Rotation + angle; if (info.IsAligned) { att.AlignmentPoint = info.Alignment.TransformBy(br.BlockTransform); att.AdjustAlignment(br.Database); } if (att.IsMTextAttribute) { att.UpdateMTextAttribute(); } } return true; } }
Hi,
Your solutions are really very useful. Sorry to confuse you. I am a fresher and very new to this autocad.net api development. The video you provided is the output I require. But the block should move below the polyline and should get placed below the polyline when clicked. the moving block is my block having attributes in it. Checking the solutions you gave , I modified my code and now I am able to jig my block along the polyline. But not below the polyline. I used block instead of dbtext, used drawjig. Taking reference from your code, I developed it. Please don't take it as I am posting for fun or wasting your time.
My requirement in clear description when I run my command is:
This is the clear requirement. Please do understand that I am serious about my task. Sorry again if I confused you . I am attaching the jig code I am using now. In that I am passing my selected entity, rotating entity . As of now my output is, jigging is not completely below the polyline. and while moving the blocks rotation is not aligned with polylines angle. but once I end moving, it is placed with that segment angle in polyline. Hope you understood my requirement and where I am in my task now. Please let me know your suggestions.
Thanks in advance.
I cannot understand why you keep on trying to do it with a DrawJig despite the fact all examples I provided use an EntityJig.
As said before, I think jigging a single entity is simpler with an EntityJig. If you absolutely want to use a DrawJig, do it so but I won't follow you on this route.
Hi _gile,
Thank you so much for your inputs and guidance. Now I implemented using entity jig with the help of your references. Thanks for the patience you have towards my posts. As I am completely new to this, I took time to get through the things. Now when I use the below code, I am able to move only below the selected polyline. When the direction on polyline is changing, the block is inverted. How can I modify the output to the one I attached as screenshot.
Please find the screenshot I attached. Need your suggestions and inputs in this regard.
Thanks in advance.
Tejaswini
You need to PI radians (180°) to the rotation angle when its cosine is negative (i.e. [90°-270°] range)
protected override bool Update() { var point = pline.GetClosestPointTo(dragPt, false); var angle = pline.GetFirstDerivative(point).AngleOnPlane(plane); if (Math.Cos(angle) < 0.0) angle += Math.PI; br.Position = point; br.Rotation = angle; foreach (var entry in attInfos) { var att = entry.Key; var info = entry.Value; att.Position = info.Position.TransformBy(br.BlockTransform); att.Rotation = info.Rotation + angle; if (info.IsAligned) { att.AlignmentPoint = info.Alignment.TransformBy(br.BlockTransform); att.AdjustAlignment(br.Database); } if (att.IsMTextAttribute) { att.UpdateMTextAttribute(); } } return true; }
Hi _gile,
After jigging and placing my block with attributes, I am getting my block position at top right of attribute value and attribute reference position at bottom left of the attribute value. I want to have the block position on top left and attribute position on bottom left ( both at same Y-position, one on top left and one on bottom left).
In the reference code you provided,
IsAligned = text.Justify != AttachmentPoint.BaseLeft; ----> at this actually my block(which I am using and giving attribute value) justification is base left for attribute definition, if I give it as equal to , I am getting eNotapplication exception at below code point.
if (info.IsAligned) {
att.AlignmentPoint = info.Alignment.TransformBy(br.BlockTransform);-----> in this line
att.AdjustAlignment(br.Database);}
Can you please help me in this. Please let me know, if you need more information regarding this.
Thanks for any kind of help.
Tejaswini.
Hi _gile,
Thanks for your response, actually I understood where I got deviated. I got the issue fixed. I calculated a perpendicular point to the block position and gave it to the attribute position, and the issue got fixed.
Thanks a lot for the guidance.
Teja.
Can't find what you're looking for? Ask the community or share your knowledge.