Get to Text objects within Imported Dwg

Get to Text objects within Imported Dwg

grahamcook
Advocate Advocate
10,347 Views
28 Replies
Message 1 of 29

Get to Text objects within Imported Dwg

grahamcook
Advocate
Advocate

Hi
I am successfully importing a dwg and extracting a collection of blocks, their coordinates and rotation.

 

Problem is I also need to get to the Text objects within the imported DWG for which the only method I know is to Explode the DWG which then reveals the Text as TextNote objects.  This gives me what i need all be it with the expense of exploding the DWG (I remove the elements after) but the issue here is that the Explode command only supports up to 10000 elements meaning I can’t get to the Text objects within the dwg Import if this limit is exceeded.

 

If anyone out there knows how to get the Text objects from a single dwg ImportInstance without Exploding first I would be extremely graceful in finding out.  Interestingly you can get to a single Text object through the UI by selecting the Imported DWG and then clicking the Query Button under the Modify Tab.

 

The simplified code that loops looking for GeometryInstance (blocks) is listed below.

 

            string FileName = "";

            ElementId elementid = null;

            DWGImportOptions options = new DWGImportOptions();
            options.SetRefPoint(new XYZ(0, 0, 0));
            options.Placement = Autodesk.Revit.DB.ImportPlacement.Centered;
            options.OrientToView = true;

            doc.Import(FileName, options, doc.ActiveView, out elementid);

            // Get hold of the imported dwg object and drill down through the
//elements picking out the blocks ImportInstance dwg = doc.GetElement(elementid) as ImportInstance; if (dwg == null) return Result.Failed; foreach (GeometryObject geometryObj in dwg.get_Geometry(new Options())) { if (geometryObj is GeometryInstance) // This will be the whole thing { GeometryInstance dwgInstance = geometryObj as GeometryInstance; foreach (GeometryObject blockObject in dwgInstance.SymbolGeometry) { if (blockObject is GeometryInstance) // This could be a block { //get the object name and coordinates and rotation and
//load into my own class clsBlockInstance blockCls = new clsBlockInstance(); GeometryInstance blockInstance = blockObject as GeometryInstance; string name = blockInstance.Symbol.Name; Transform transform = blockInstance.Transform; XYZ origin = transform.Origin; XYZ vectorTran = transform.OfVector(transform.BasisX.Normalize()); double rot = transform.BasisX.AngleOnPlaneTo(vectorTran, transform.BasisZ.Normalize()); // radians rot = rot * (180 / Math.PI); // degrees blockCls.Name = name; blockCls.Origin = origin; blockCls.Rotation = rot; blockInstanceCollection.Add(blockCls); } } } }

 

0 Likes
10,348 Views
28 Replies
Replies (28)
Message 2 of 29

arnostlobel
Alumni
Alumni
Hello grahamcook:

I am sorry to say that there is no way to get to text objects in an imported DWG which hasn't been exploded. That is in fact no different for an API user than it is for an internal Revit developer. The reason is that there are no actual text objects (i.e. instances of TextNote or TextElement classes as you may know them) in the imported symbol. It is only after the symbol is exploded when Revit takes the text data from inside the symbol and creates proper text elements out of them.
Arnošt Löbel
0 Likes
Message 3 of 29

grahamcook
Advocate
Advocate

Thanks Arnost for clarifying that.  Back to the drawing board for me then!

 

It would be good when faced with an issue like this to have an override to the 10,000 limit.  As it stands I see no way of getting to those text objects in large files without being able to do a partial Explode on them.

 

I guess a work around might be to split the AutoCAD file up but I have no control over that on this site and whether the users even have access to AutoCAD.

 

Regards

 

Graham Cook

0 Likes
Message 4 of 29

grahamcook
Advocate
Advocate

Arnost

 

You mentioned in your answer that an internal Revit developer would also need to explode the import instance in order to get to the text data.  By internal Revit developer I assume you mean the guys that develop the Revit package there at Autodesk?  If so then they do appear to be getting to the text data without exploding the import instance as the following image shows.  Maybe they are exploding in the background and don't have the same 10,000 element restriction the API has but the data is available almost instantaneously so I doubt it is being exploded.

 

ImportInstanceQuery.jpg

 

Graham Cook

0 Likes
Message 5 of 29

arnostlobel
Alumni
Alumni

Grahamcook:

 

Indeed, by "internal developers" I meant us, programmers who develop Revit. And it is true what I said: we cannot get the text data in an imported symbol in the form of Text Element (or TextNote.)  We are not exploding the symbol in the background and we do face the same 10000 piece limit. However, we can still get to the text inside of it, naturally. Until the symbol is exploded the data is in a form for which there is no public API. I'd be skeptical about exposing this internal format in the public API. There may be other solutions though, but at this moment I cannot say what it is going to be and when a solution would be made available.

 

I can make sure, though, that this case is logged as a customer's request.  May I ask what information about the text do you need to get out of the symbol in your particular case? Is it everything you would get from a regular TextNote, or would some subset of text information suffice?

 

Thank you

Arnošt Löbel
0 Likes
Message 6 of 29

grahamcook
Advocate
Advocate

Arnošt

 

Essentially the bigger picture here is a block to family AddIn.

 

Regarding what part of the text data i need to get to, it is simply the Text value that the user sees on the screen and its position.  The imported DWG contains blocks with attribute tags which are placed in the centre of each block.  So once i have a collection of blocks (or GeometryInstance's as i understand them) using the code in my original post, i explode the DWG Import instance, get a collection of all the TextNote objects (which are now available), and then match them up with their corresponding block by comparing the bounding box of each (if the TextNote fulls within the boundingBox of a block then the TextNote belongs to that block).  This was the only way i could figure out of how to associate a TextNote with its corresponding block but may have missed something here.  The value of those attributes is crucial in determining what family to place.

 

The AddIn is working very well on small to medium plans but on larger plans the 10,000 limit brings the pack of cards down!

 

I appreciate your insight and for logging a customer request.

 

Regards

 

Graham Cook

0 Likes
Message 7 of 29

Anonymous
Not applicable

It might be possible to get your hands dirty and parse the dwg natively using an external dll? Sounds like a long and arduous path though.

 

As another suggestion, most Revit users will also have AutoCAD installed (whether they use it or not). You could maybe access what you need through an automated instance (does TrueView have an API?). I've not done any of these so can't offer any details, I just thought I'd throw a few ideas out there.

 

I can't stand a problem without a solution. Smiley Mad

 

 

0 Likes
Message 8 of 29

PaulCollins7972
Advocate
Advocate

Arnošt

 

You were asking what use the text information would be put to.

I have also been hoping to read text from an import instance. Geometry can be read but not the text!

In my case I was hoping to read the levels in a topographic survey and use them to create points in a topo surface, so I was hoping to read the text value and its location only. Not interested in font etc.

 

Regards

 

Paul Collins

0 Likes
Message 9 of 29

arnostlobel
Alumni
Alumni
Paul at al,

All I can do now is to forward your request to the team that "owns" , maintains, and actively develops the Text features in Revit. As we had previously discussed above, it is not currently possible to get to the text entities inside an imported DWGs. Internally (in Revit core code) we have some ways to examine the text there, but the info we get from those objects is actually not the common text like in text notes etc. The DWG text entities basically know how to draw themselves, and Revit does not need to get too involved there. Once a DWG instance is exploded, text entities get converted to regular text elements, which become Revit's responsibility and can be accessible.

Again, I will forward this to the text team. I cannot promise anything on their behalf, however, although I am confident they'll do what they can.

Thank you
Arnošt Löbel
0 Likes
Message 10 of 29

PaulCollins7972
Advocate
Advocate

Arnošt

 

Thanks, understand that it is not possible right now.

I thought that an example use would be helpful

Message 11 of 29

Dale.Bartlett
Collaborator
Collaborator

"It might be possible to get your hands dirty and parse the dwg natively using an external dll?"

Given limitations with accessing DWG data, this is a reasonable and reliable solution. I have a Revit addin that generates a Space-Frame roof truss from an AutoCAD analysis stick drawing. The geometry is first exported from AutoCAD as an XML file and then read into Revit. It has run up to 20,000 elements so is one way to get over the barrier. I personally think this would be a more robust solution. Any information you want from AutoCAD can be exported accurately and then regenerated however you want in Revit. Dale




______________
Yes, I'm Satoshi.
Message 12 of 29

27925916
Advocate
Advocate

hello,did you find theway to get text objects within imported Dwg without explode? I am also confused on it .Smiley Embarassed

Message 13 of 29

PaulCollins7972
Advocate
Advocate

Hi

 

Yes I managed to read the text objects but not directly from a DWG that is linked/inserted into Revit.

 

My add-in creates a topo surface based on a linked/inserted DWG, so I wanted to read the text that gave the levels on the surveyors drawing.

 

What I did was to make my add-in export to a DXF file and then read the levels from that. 

 

I now have a working add-in for Revit 2014, 2015, 2016 and 2017 which has been deployed to everyone in our offices. The user just starts the add-in, confirms which DWG to read if there is more than one to choose from and a Topo surface is created which matches the surveyors drawing.

 

Regards

 

 

0 Likes
Message 14 of 29

27925916
Advocate
Advocate

you mean export a dxf file and read text infomation from it ,and then delete this dxf file after reading?

0 Likes
Message 15 of 29

PaulCollins7972
Advocate
Advocate

Yes that's it.

 

So I ask the user to get the view in Revit to only include the required layers which show levels before running my add-in.

 

  1. In the add-in I read the layers which are visible in the DWG
  2. Create a temporary DXF in the users add-in folder. This actually gets deleted on the next run as it may help to see what is created if add-in fails
  3. read the offset origin of the DWG in the DXF, this is used when building a list of coordinates so that they match the position of the survey
  4. read all the points on the visible layers and apply offset. So the X and Y are from the plan coordinate, the Z is read from the text
  5. create a new topo surface using all the points read in step 4
  6. the Revit view is adjusted to ensure that the results are displayed, the Topo category is included and the View Depth adjusted

 

 

Message 16 of 29

27925916
Advocate
Advocate

thanks a lot ,Smiley Very Happy I think it is a good way ,I want to take  a try to read text in linked dwg and match it with corresponding line  in yourway。

and I am having a doubt whether the elementID of line and text in revit could be the same with the one in exported dxf?   and if you have any sample for exporting dxf and reading text's position and content to match the linked dwgSmiley Embarassed

I am no sure if I have expressed myself clearly.

I am exceedingly looking forward your helpSmiley Embarassed

0 Likes
Message 17 of 29

27925916
Advocate
Advocate

did you use DWGExportOption to output a dxf file, and then use DWGImportOption to read text in it ?

0 Likes
Message 18 of 29

PaulCollins7972
Advocate
Advocate

I used this code to export the current view to DXF:

 

            DXFoptions.LayerMapping = "BS1192"
            DXFoptions.SharedCoords = False
            DXFoptions.TargetUnit = ExportUnit.Meter
            DXFoptions.FileVersion = ACADVersion.R2007

            doc.Export(DXF_Folder, DXF_File, DXF_Views, DXFoptions)

 

(I chose DXF not DWG because that meant that I could use text manipulation tools to read the file.)

 

and then used Streamreader to read the resulting file:

 

            Using r As StreamReader = New StreamReader(Filename)
                ' Read first line.
                line = r.ReadLine

                ' Loop over each line in file until the end
                Do While (Not line Is Nothing)

                    If UCase(line) = "ACDBENTITY" Then
                        EntityCount = EntityCount + 1
                        ' "8" is the code for the layer name
                        LayerName = ReadCodeFromFile(r, "8")

                        For Each lay In Layers
                            If LayerName = lay Then
                                'the next line may be 62 if the entity is not color bylayer
                                'or 100 if color bylayer

                                ' "100" is the code for the subclass marker
                                EntityType = ReadCodeFromFile(r, "100")

                                'only get MTEXT entries
                                If UCase(EntityType) = "ACDBMTEXT" Then

                                    'load the relevant lines from the file into an array and use that to read values
                                    'because the order of the section codes should not be relied on
                                    DxfDef.Clear()
                                    Dim code As String = vbNullString
                                    Dim value As String = vbNullString

                                    'Do Until value = "ENDBLK" Or value = "ENDSEC"
                                    'code "1" is the Text Marker
                                    Do Until code = "1"
                                        code = Trim(r.ReadLine)
                                        value = Trim(r.ReadLine)
                                        DxfDef.Add(New KeyValuePair(Of String, String)(code, value))
                                    Loop

 

I read the Autodesk  DXF File Format document to figure out how to read what I was interested in from the DXF file.....

0 Likes
Message 19 of 29

27925916
Advocate
Advocate

Smiley LOLI know what you mean now.   I have some question, one is how is its cost of time?  I just want to get all text content of dimension like you .

 

and the other question is that how do you connect the text's position with the one in dwg linked into revit?

0 Likes
Message 20 of 29

PaulCollins7972
Advocate
Advocate

Not sure I understand your first point.

 

The position was easy because the coordinates are stored with the text entry in the DXF file, the coordinates match the Revit internal position as I set the option to export the internal not shared coordinate in the DXFoptions

 

DXFoptions.SharedCoords = False

 

My routine for reading the text also reads the X and Y positions. I have found that this is actually the top left corner of the text primitive.

 

I used the info to create a topo surface coordinate which ends up in the same place as the text in the survey DWG.

0 Likes