ObjectARX
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Things to follow in dxfOutFields

1 REPLY 1
Reply
Message 1 of 2
Juhas0
374 Views, 1 Reply

Things to follow in dxfOutFields

Hi, I have a very big problem with dxf files. My custom entity consists of other primitive entities (lets say: lines, multitexts and circles). But types and quantities are variable. So one instance of my entity will consist of 2 lines and the other of line and circle.

 

I'm trying to save and load the info using dxf file. What I learnt so far is:

1. When you save embedded object, first you have to call: filer->writeEmbeddedObjectStart() and then you can call object's dxfOutFields

2. When you load embedded object, first you have to call: if(filler->atEmbeddedObjectStart())... and then you can call object's dxfInFields

3. You cannot have other values between two embedded objects! (why?)

 

When I'm trying to put some info between two embedded objects I get kdxfInvalid instead of actual value type. In my case this would be desireable because firts I would save info about object type (as int, ie. 1 for line, 2 for circle etc) and then the object. But it doesn't work. So I have to first save info about all object types and then objects.

 

After all objects are saved, I would like to have some more data, but the situation is the same. When I try to read data (after last object), I get kdxfInvalid instead of actual value type. Why is that?

 

Here is fragment of my code:

Acad::ErrorStatus ARXEntity::dxfOutFields(AcDbDxfFiler* filer) const
{	
	assertReadEnabled();

	
	ErrorStatus es = AcDbEntity::dxfOutFields(filer);
	if(es != Acad::eOk) return es;

	filer->writeItem(AcDb::kDxfSubclass, L"ARXEntity");

	//entities count
	filer->writeInt32(AcDb::kDxfInt32, m_entities->size());

	//entities types
	for(Entities::iterator it = m_entities->begin(); it != m_entities->end(); ++it) 
	{
		filer->writeInt32(AcDb::kDxfInt32, int(it->second));
	}

	//entities
	for(Entities::iterator it = m_entities->begin(); it != m_entities->end(); ++it) 
	{
		filer->writeEmbeddedObjectStart();
		it->first->dxfOutFields(filer);
	}


	//grips
	filer->writeInt32(AcDb::kDxfInt32, m_gripPoints->size());
	for(GripPoints::iterator it = m_gripPoints->begin(); it != m_gripPoints->end(); ++it)
	{
		filer->writePoint3d(AcDb::kDxfXCoord, *it);
	}

	return filer->filerStatus();
}


Acad::ErrorStatus ARXEntity::dxfInFields(AcDbDxfFiler* filer)
{
	assertWriteEnabled();	
	
	Acad::ErrorStatus es = AcDbEntity::dxfInFields(filer);
	if(es != Acad::eOk) return es;

	if(!filer->atSubclassData(L"ARXEntity")) return Acad::eBadDxfSequence;

	resbuf rb;
		
	//entities count
	es = filer->readResBuf(&rb);
	if(rb.restype != kDxfInt32) ThrowDXFException(kDxfInt32, rb.restype);
	int entCount = rb.resval.rlong;

	if((entCount) && (!m_entities)) m_entities = new Entities();

	//entities types
	std::vector<claas::EntityType::Enum> eTypes;

	for(size_t i = 0; i < entCount; ++i)
	{
		es = filer->readResBuf(&rb);
		if(rb.restype != kDxfInt32) ThrowDXFException(kDxfInt32, rb.restype);
		eTypes.push_back(EntityType(rb.resval.rlong));
	}

	AcDbEntity * ent;
        //entities  
	for(size_t i = 0; i < entCount; ++i)
	{			
		if(filer->atEmbeddedObjectStart())
		{
			switch(eTypes[i]) 
			{
			case EntityType::Circle:
				ent = new AcDbCircle;
				((AcDbCircle *)ent)->dxfInFields(filer);
				break;

			case EntityType::Line:
				ent = new AcDbLine();
				((AcDbLine *)ent)->dxfInFields(filer);
				break;

			case EntityType::MultilineText:
				ent = new AcDbMText();
				((AcDbMText *) ent)->dxfInFields(filer);
				break;

			} else
				throw "No object start";

			(*m_entities)[ent] = eTypes[i];
		}


		//grips
		es = filer->readResBuf(&rb);
		if(rb.restype != kDxfInt32) ThrowDXFException(kDxfInt32, rb.restype);
                //here my rb.restype is -9999 instead of 90, why?
		int gripsLen = rb.resval.rlong;

        //some other code
	return filer->filerStatus();
}

 

So, what's wrong with this code?

Tags (1)
1 REPLY 1
Message 2 of 2
artc2
in reply to: Juhas0

There needs to be some marker group to indicate when one object's data ends and another object's data starts so that readResBuf() knows when to return a non-eOk value to indicate that an object's data has ended.  These would be the group codes that indicate the start of xdata, or another object (group 0), or an embedded entity (101), or a different class's data (i.e. group 100).  This is necessary because objects' dxfInFields() methods rely on readResBuf() returning non-eOk to tell when their data is done and it's time to return.

 

I've never tested it, but you should be able to use a group 100 as a separator between your embedded entity data and the data you want to write.  Something like this:

 

In your dxfOutFields:

 write your subclassdata marker

 write your data

 call writeEmbeddedObjectStart

 call dxfOutFields on the embedded object

 write a subclass data marker (k.e. AcZDb::kDxfSubclass)

 write data you want

 call write EmbeddedObjectStart

 call dxfOutFields on next embedded object

 write a subclass data marker

 wirte data you want

 repeat until done

 

In dxfInFields

 

 call your base class's dxfInFields()

 call atSubclassData() to get past your first subclass data marker

 read your data until readResBuf() returns non-eOk

 check atEmbeddedObjectStart and if so, then call dxfInFields on embedded object

 call atSubclassData to get past the subclass data marker you wrote after the embedded object's data

 read your data until readResBuf() returns non-eOk

 check atEmbeddedObjectStart and if so, then call dxfInFields on embedded object

 call atSubclassData to get past the subclass data marker you wrote after the embedded object's data

 read your data until readResBuf() returns non-eOk.

 repeat until done

 

When you write the subclassData markers, you can use any string you want.  It can be the same for all of them, or different for each.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost