I have created a NET routine which, when executed, creates a schematic drawing representation of the parent (active drawing). All of the procedures execute as they should, however one is a mystery. HATCH
On the schematic (inactive document) the hatch appears with the Autocad default settings for the pattern used. The properties that I am looking at are: The pattern scale and the hatch angle.
The new hatch pattern is displayed with a pattern scale of 1.0 and a hatch angle of 0.0 when they should be displayed with a pattern scale of 0.5 and a hatch angle of 45
Upon reviewing the hatch properties, by double clicking on the offending hatch pattern, I find that the values are are correct and as expected (0.5 and 45). By closing the hatch property dialog, the hatch pattern updates itself.
Why doesn't this occur automatically, even linetypes do not appear correctly until a regen is manually involked?
Is it because the hatch pattern or other elements are not being drawn on the active document?
Is this just Autocad?
I have attempted to do the same test via COM and the results are the same.
I have relentlessly searched for documentation on this occurance whithout much success and
I can't believe that no one programically creates supporting documents from a parent drawing.
Below is some code:
' ' Create the hatch object and append it to the block table record Dim acHatch As Hatch = New Hatch() ' ' Set the properties of the hatch object acHatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31") acHatch.PatternScale = 0.5 acHatch.PatternAngle = Math.PI * 0.25 ' ' Add the hatch object to the new database. If these 3 lines of code ' are before the pattern settings an "eAmbiguousObject" error will ' occur when the hatch object is evaluated. acHatch.SetDatabaseDefaults(acNewDb) acBlkTblRec.AppendEntity(acHatch) acTrans.AddNewlyCreatedDBObject(acHatch, True) ' ' Define the host working database. If this is not added here the ' hatch does not appear until the document is saved and reopened HostApplicationServices.WorkingDatabase = acHatch.Database acHatch.Associative = True acHatch.AppendLoop(HatchLoopTypes.[Default], acObjIdColl) acHatch.EvaluateHatch(True) ' ' Save the new object to the database acTrans.Commit()
Solved! Go to Solution.
Solved by hperison. Go to Solution.
Hi,
just one idea (haven't tried your code): what happens, if you do the .AppenLoop and .EvaluateHatch before you add the hatch-object to the blocktablerecord and to the transaction?
- alfred -
I had to look at my own code to verify this, but what will happen (if you .AppendLoop before adding the hatch to the database) is you will get an eNotInDatabase exception.
The order of his set properties, then add to the database, then make associative and append loop is the same order as my code. I don't experience the same problems he does, but my code works with the active document.
So, my question to the OP is, you say it is an inactive drawing, but does that mean the document is open in the editor, and not active, or is it a side database that is not open in the editor?
Either way you could try calling acHatch.Database.TransactionManager.QueueForGraphicsFlush()
If it is open in the editor, you could try calling Editor.Regen (once at the end of your code).
There is also a RecordGraphicsModified(bool) method, but according to the SDK help files the default is True, which is supposed to Update the entity when it is closed.
On a different note, you might have this somewhere else but it is not in the code you have shown, make sure that you reset the WorkingDatabase back to the original Database.
My code sample is almost the same as that of the AutoCad documentation. However, unlike the documentation, if I do not define the Hatch Pattern Type before appending to the BlockTable record I encounter an eAmbiguousOutput error. With this in mind it does not matter to much where I set the PatternScale and Pattern Angle values. I just opted to keep the m all together for simplicity.
Unlike the documentation, I had already previously defined the hatch boundary, so all that was necessary was to supply the ObjectID Collection. I have also had to specify what database default to implement as well as establish the working database.
If you examine your idea, it won't work because according to the Autocad documentation:
"When you have finished defining the hatch it must be evaluated before it can be displayed.
Use the EvaluateHatch method to do this."
Therefore, the Hatch object must be fully defined before the evaluation can be performed. If one does as you have suggested an eNotInDatabase error will be encountered.
It appears that in order for the required changes to be displayed in a non-active document, which is open in the editor, the non-active document must be made the 'current' document when the changes occur. The API that does that is not exposed to managed code, and it can't be P/Invoked either. To make the non-active document the 'current' document causes the main execution to be halted until the parent document becomes active again. This is not the desired effect that I am looking for.
It appears that I may have to create a custom hatch pattern to achieve the desired results that I am looking for instead of using the Autocad available Hatch patterns.
To answer your question chief,
"So, my question to the OP is, you say it is an inactive drawing, but does that mean the document is open in the
editor, and not active, or is it a side database that is not open in the editor?"
The inactive drawing is one that is open in the editor but does not have the focus. It is being programically populated by elements extracted from the active drawing where the code has be executed from.
In other words: Active Drawing = MDIDocument(0)
InactiveDrawing = MDIDocument(1)
"If it is open in the editor, you could try calling Editor.Regen (once at the end of your code)."
I have attempted this, without any success as the hatch pattern must be opened from the properties manager and the values accepted as displayed in order for the hatch to display as expected.
I am going to test some of the other suggestions that you have provided.
Thanks
Chief, you wrote:
"Either way you could try calling acHatch.Database.TransactionManager.QueueForGraphicsFlush()"
- Exception eNotOfThisDatabase Doesn't matter how I do this or where, I get the same exception result
"There is also a RecordGraphicsModified(bool) method, but according to the SDK help files the default is True,
which is supposed to Update the entity when it is closed."
- I agree and this shouldn't be an issue
"On a different note, you might have this somewhere else but it is not in the code you have shown, make sure
that you reset the WorkingDatabase back to the original Database."
- Yes, this was taken care of
Thanks - No worries, This is just an annoyance rather then anything else. I think that I will simply create my own custom hatch pattern or hatch function to suit my needs.
oddly enough, I have a couple of hatch functions (one generic, and one very specific) and neither of them call .EvaluateHatch, but both functions work fine.
obviously that is irrelevant though.
You can however activate the second document using managed code. Your comment regarding this leads me to believe that you do not have the CommandFlag.Session set?
You need that, then you should just be able to set the DocumentCollection.MdiActiveDocument = MyDoc
"Either way you could try calling acHatch.Database.TransactionManager.QueueForGraphicsFlush()"
- Exception eNotOfThisDatabase Doesn't matter how I do this or where, I get the same exception result
First, I was not confident that it would solve the problem, but still, the exception is wierd, since the way I wrote it there specifically obtains the TransactionManager from the Database that the acHatch is in, so how could it be NotOfThisDatabase? 😛
Isn't that interesting. I commented out the .EvaluateHatch and found that the code worked fine too.
I guess that goes to show that even the net samples have some flaws or residual elements from earlier days.
By removal of this code I am not restricted as to the line location of my property values placement.
CommandFlag.Session set? Not anymore, I did have at one point. I will rest this and try again.
Lastly, eNotOfThisDatabase - Has me baffled too
I am keeping my code for futher evaluation. Sometimes I am like a dog with a bone in these matters.
FYI, You do still have to SetHatchPattern before setting PatternAngle.
As far as the Session flag, if you can get away without it, you should. I only mentioned it since it seemed like the only way to make the code work right was going to be activating the other document, in which case you would need the Session flag, but if you can get the code to work without activating the document, then do that and skip the session flag.
In my opinion, "like a dog with a bone" is the way to be 😉 Just accepting it and moving on doesn't really teach you anything. So I tend to be like a Pit Bull with a bone and sink my teeth in and don't let go until I understand why.
This is the first time I have ever needed to do any hatching in NET and felt that I had nothing wrong with what I was originally doing. Consequently, I have gone back to square 1 and decided to actually evaluate the Hatch example contained within the AutoCad NET Developers guide.
LOL it does exactly the same thing as my code. I have to double-click on the hatch pattern drawn within the active drawing and accept the current values before the hatch pattern will change.
So obviously I have missed something here that was not hinted at in the Developers Guide and need to do some further investigation. I am going to have to get the initial code correct before proceding any further.
I will post the correct coding procedure when I am finished so others will not go down this same road.
Thanks for your help
The code example contained within the AutoCAD NET Developers Guide does not provide
for arbitrary pattern values. It is simply a rudimentary code sample that reflects the means
of adding a Hatch pattern to a drawing. That is fine if that is what is needed. For setting the
Hatch pattern to a variable set of values the hatch pattern code can be as follows:
Dim acHatch As Hatch = New Hatch() ' 'Add the hatch to the block table record and the transaction acBlkTblRec.AppendEntity(acHatch) acTrans.AddNewlyCreatedDBObject(acHatch, True) acHatch.SetDatabaseDefaults(acSpoolDb) ' ' Change from read to write mode acHatch.UpgradeOpen() ' 'set the Hatch properties acHatch.Associative = True acHatch.PatternScale = 0.5 acHatch.PatternAngle = Math.PI * 0.25 acHatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31") ' ' Change from write to read mode acHatch.DowngradeOpen() ' 'Attach to boundary loop acHatch.AppendLoop(HatchLoopTypes.[Default], acObjIdColl) ' ' Save the new hatch object to the database acTrans.Commit()
For me the CommandFlag.Session flag was set in order for the hatch to display.
If one has a better way of adding hatching that accepts differing parameters and displays correctly, then by all means share.
You sure about that?
I'm getting confused now. I was playing around with the example in the developers guide, and was just getting ready to post a comment here when you posted your last one.
I was getting the hatch showing up with the right pattern angle, but the wrong scale, regardless of calling evaluate hatch or not.
And even with the code you just posted, I am still getting an eInvalidInput Exception unless I move the PatternAngle setting to after calling SetHatchPattern.
Now it is getting even wierder, because I have gone back to the original Developer guide code, added two lines to set the PatternAngle and PatternScale, and now it is working fine. I have three separate functions each slightly different, and all three are working fine.
If I take any of the three and move the PatternAngle setting to before the SetHatchPattern call, they all fail, eInvalidInput.
Hi,
>> unless I move the PatternAngle setting to after calling SetHatchPattern
Did you ever verify on what AutoCAD releases you are working? Because the order for PatternAngle before or after SetHatchPattern is depending on AutoCAD-release!
I use this code working now from 2007 to 2012, not yet tested with 2013
If ISHAcConn.AcadApp_VersionDouble < 18.1 Then Hatch.PatternAngle = (RotationDegree / 180 * Math.PI) End If
Hatch.SetHatchPattern(DatabaseServices.HatchPatternType.PreDefined, tPatternName) If ISHAcConn.AcadApp_VersionDouble >= 18.1 Then Hatch.PatternAngle = (RotationDegree / 180 * Math.PI) End If
BTW: I'm really surprised that the hatch-creation is working without the .EvaluateHatch
- alfred -
Due to my excitement in getting this to finally work I made an error in my latest code.
UpgradeOpen and DowngradeOpen lines are not required and do nothing. I have subsequently
removed those lines and the code still works as desired.
During my attempts to remedy the problem, I had a suspicion that sequence order was important
and was moving the order around without much success in getting the correct sequence. Upon review
of my original post, I see where I have gone astray.
I am using a AutoCAD 2010 - 64bit platform with VS2010 Pro
Thank you Alfred, as I am glad to know that I am going to need to implement a caveat for later versions of Autocad.
I think this can be put to rest now
Hi Chief,
I have the same problem with the hatch scale. I've tried re-arranging the hatch properties, but I just can't seem to get it to visually show the correct hatch scale. When I pick the hatch and view its properties, it shows the right hatch scale, but visually it's wrong. Can you take a look and see where I might be going wrong?
Public Sub AddIndexArea(ByVal leftX As Double, ByVal rightX As Double, ByVal bottomY As Double, ByVal topY As Double, dwg_scale As Double) ' Get the current document and database Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument Dim acCurDb As Database = acDoc.Database ' Start a transaction Using a1IndexAreaTrans As Transaction = acCurDb.TransactionManager.StartTransaction() ' Open the Block table for read Dim acBlkTbl As BlockTable acBlkTbl = a1IndexAreaTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) ' Open the Block table record Model space for write Dim acBlkTblRec As BlockTableRecord acBlkTblRec = a1IndexAreaTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite) ' Create a rectangle object for the boundary of the hatch Dim a1IndexArea As New Autodesk.AutoCAD.Geometry.Point3dCollection a1IndexArea.Add(New Geometry.Point3d(leftX, bottomY, 0)) a1IndexArea.Add(New Geometry.Point3d(rightX, bottomY, 0)) a1IndexArea.Add(New Geometry.Point3d(rightX, topY, 0)) a1IndexArea.Add(New Geometry.Point3d(leftX, topY, 0)) Dim a1IndexAreaPLine As New DatabaseServices.Polyline2d(DatabaseServices.Poly2dType.SimplePoly, a1IndexArea, 0, True, 0, 0, Nothing) acBlkTblRec.AppendEntity(a1IndexAreaPLine) a1IndexAreaTrans.AddNewlyCreatedDBObject(a1IndexAreaPLine, True) ' Adds the rectangle to an object id collection Dim a1IndexAreaIdColl As ObjectIdCollection = New ObjectIdCollection() a1IndexAreaIdColl.Add(a1IndexAreaPLine.ObjectId) acCurDb.TransactionManager.QueueForGraphicsFlush() ' Create the hatch object and append it to the block table record Dim acHatch As Hatch = New Hatch() acBlkTblRec.AppendEntity(acHatch) a1IndexAreaTrans.AddNewlyCreatedDBObject(acHatch, True) ' Set the properties of the hatch object ' Associative must be set after the hatch object is appended to the block table record acHatch.SetDatabaseDefaults() acHatch.Associative = True acHatch.SetHatchPattern(HatchPatternType.PreDefined, "ANSI31") acHatch.PatternScale = dwg_scale acBlkTblRec.SetObjectIdsInFlux() acHatch.AppendLoop(HatchLoopTypes.Outermost, a1IndexAreaIdColl) acHatch.EvaluateHatch(True) ' Save the new object to the database a1IndexAreaTrans.Commit() End Using End Sub
Thanks,
Mark