mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 06:58:56 +00:00
- Getting ready for Blender 2.65 and Python 3.3.0 with universal Unicode according to PEP 393
- Allow opening of non-latin filenames on Windows, by using the non-standard _wfopen(), meaning that the IfcSpfStream no longer relies on a std::istream but a FILE* descriptor
This commit is contained in:
@@ -30,8 +30,8 @@ bl_info = {
|
|||||||
"description": "Import files in the "\
|
"description": "Import files in the "\
|
||||||
"Industry Foundation Classes (.ifc) file format",
|
"Industry Foundation Classes (.ifc) file format",
|
||||||
"author": "Thomas Krijnen, IfcOpenShell",
|
"author": "Thomas Krijnen, IfcOpenShell",
|
||||||
"blender": (2, 5, 8),
|
"blender": (2, 6, 5),
|
||||||
"api": 37702,
|
"api": 52851,
|
||||||
"location": "File > Import",
|
"location": "File > Import",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
"wiki_url": "http://sourceforge.net/apps/"\
|
"wiki_url": "http://sourceforge.net/apps/"\
|
||||||
@@ -39,14 +39,6 @@ bl_info = {
|
|||||||
"tracker_url": "http://sourceforge.net/tracker/?group_id=543113",
|
"tracker_url": "http://sourceforge.net/tracker/?group_id=543113",
|
||||||
"category": "Import-Export"}
|
"category": "Import-Export"}
|
||||||
|
|
||||||
import sys
|
|
||||||
max_unicode = 0x110000-1 if sys.platform[0:5] == 'linux' else 0x10000-1
|
|
||||||
wrong_unicode = max_unicode != sys.maxunicode
|
|
||||||
if wrong_unicode:
|
|
||||||
print("\nWarning: wrong unicode representation detected, switching to "\
|
|
||||||
"compatibility layer for text transferral, may result in undefined "\
|
|
||||||
"behaviour, please use offical release from http://blender.org\n")
|
|
||||||
|
|
||||||
if "bpy" in locals():
|
if "bpy" in locals():
|
||||||
import imp
|
import imp
|
||||||
if "IfcImport" in locals():
|
if "IfcImport" in locals():
|
||||||
@@ -71,15 +63,9 @@ bpy.types.Object.ifc_type = StringProperty(name="IFC Entity Type",
|
|||||||
|
|
||||||
|
|
||||||
def import_ifc(filename, use_names, process_relations):
|
def import_ifc(filename, use_names, process_relations):
|
||||||
global wrong_unicode
|
|
||||||
from . import IfcImport
|
from . import IfcImport
|
||||||
print("Reading %s..."%bpy.path.basename(filename))
|
print("Reading %s..."%bpy.path.basename(filename))
|
||||||
if wrong_unicode:
|
valid_file = IfcImport.Init(filename)
|
||||||
valid_file = IfcImport.InitUCS2(
|
|
||||||
''.join(['\0']+['\0%s'%s for s in filename]+['\0\0'])
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
valid_file = IfcImport.Init(filename)
|
|
||||||
if not valid_file:
|
if not valid_file:
|
||||||
IfcImport.CleanUp()
|
IfcImport.CleanUp()
|
||||||
return False
|
return False
|
||||||
@@ -92,18 +78,11 @@ def import_ifc(filename, use_names, process_relations):
|
|||||||
while True:
|
while True:
|
||||||
ob = IfcImport.Get()
|
ob = IfcImport.Get()
|
||||||
|
|
||||||
if wrong_unicode:
|
|
||||||
ob_name = ''.join([chr(c) for c in ob.name_as_intvector()])
|
|
||||||
ob_type = ''.join([chr(c) for c in ob.type_as_intvector()])
|
|
||||||
ob_guid = ''.join([chr(c) for c in ob.guid_as_intvector()])
|
|
||||||
else:
|
|
||||||
ob_name, ob_type, ob_guid = ob.name, ob.type, ob.guid
|
|
||||||
|
|
||||||
f = ob.mesh.faces
|
f = ob.mesh.faces
|
||||||
v = ob.mesh.verts
|
v = ob.mesh.verts
|
||||||
m = ob.matrix
|
m = ob.matrix
|
||||||
t = ob_type[0:21]
|
t = ob.type[0:21]
|
||||||
nm = ob_name if len(ob_name) and use_names else ob_guid
|
nm = ob.name if len(ob.name) and use_names else ob.guid
|
||||||
|
|
||||||
verts = [[v[i], v[i + 1], v[i + 2]] \
|
verts = [[v[i], v[i + 1], v[i + 2]] \
|
||||||
for i in range(0, len(v), 3)]
|
for i in range(0, len(v), 3)]
|
||||||
@@ -138,9 +117,9 @@ def import_ifc(filename, use_names, process_relations):
|
|||||||
bpy.ops.object.mode_set(mode='OBJECT')
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
bob.ifc_id, bob.ifc_guid, bob.ifc_name, bob.ifc_type = \
|
bob.ifc_id, bob.ifc_guid, bob.ifc_name, bob.ifc_type = \
|
||||||
ob.id, ob_guid, ob_name, ob_type
|
ob.id, ob.guid, ob.name, ob.type
|
||||||
|
|
||||||
bob.hide = ob_type == 'IfcSpace' or ob_type == 'IfcOpeningElement'
|
bob.hide = ob.type == 'IfcSpace' or ob.type == 'IfcOpeningElement'
|
||||||
bob.hide_render = bob.hide
|
bob.hide_render = bob.hide
|
||||||
|
|
||||||
if ob.id not in id_to_object: id_to_object[ob.id] = []
|
if ob.id not in id_to_object: id_to_object[ob.id] = []
|
||||||
@@ -173,20 +152,9 @@ def import_ifc(filename, use_names, process_relations):
|
|||||||
if parent_ob.id == -1:
|
if parent_ob.id == -1:
|
||||||
bob = None
|
bob = None
|
||||||
else:
|
else:
|
||||||
if wrong_unicode:
|
|
||||||
parent_ob_name = ''.join(
|
|
||||||
[chr(c) for c in parent_ob.name_as_intvector()])
|
|
||||||
parent_ob_type = ''.join(
|
|
||||||
[chr(c) for c in parent_ob.type_as_intvector()])
|
|
||||||
parent_ob_guid = ''.join(
|
|
||||||
[chr(c) for c in parent_ob.guid_as_intvector()])
|
|
||||||
else:
|
|
||||||
parent_ob_name, parent_ob_type, parent_ob_guid = \
|
|
||||||
parent_ob.name, parent_ob.type, parent_ob.guid
|
|
||||||
|
|
||||||
m = parent_ob.matrix
|
m = parent_ob.matrix
|
||||||
nm = parent_ob_name if len(parent_ob_name) and use_names \
|
nm = parent_ob.name if len(parent_ob.name) and use_names \
|
||||||
else parent_ob_guid
|
else parent_ob.guid
|
||||||
bob = bpy.data.objects.new(nm, None)
|
bob = bpy.data.objects.new(nm, None)
|
||||||
|
|
||||||
mat = mathutils.Matrix((
|
mat = mathutils.Matrix((
|
||||||
@@ -201,7 +169,7 @@ def import_ifc(filename, use_names, process_relations):
|
|||||||
|
|
||||||
bob.ifc_id = parent_ob.id
|
bob.ifc_id = parent_ob.id
|
||||||
bob.ifc_name, bob.ifc_type, bob.ifc_guid = \
|
bob.ifc_name, bob.ifc_type, bob.ifc_guid = \
|
||||||
parent_ob_name, parent_ob_type, parent_ob_guid
|
parent_ob.name, parent_ob.type, parent_ob.guid
|
||||||
|
|
||||||
if parent_ob.parent_id > 0:
|
if parent_ob.parent_id > 0:
|
||||||
id_to_parent[parent_id] = parent_ob.parent_id
|
id_to_parent[parent_id] = parent_ob.parent_id
|
||||||
@@ -227,9 +195,8 @@ def import_ifc(filename, use_names, process_relations):
|
|||||||
if process_relations:
|
if process_relations:
|
||||||
print("Done processing relations")
|
print("Done processing relations")
|
||||||
|
|
||||||
if not wrong_unicode:
|
txt = bpy.data.texts.new("%s.log"%bpy.path.basename(filename))
|
||||||
txt = bpy.data.texts.new("%s.log"%bpy.path.basename(filename))
|
txt.from_string(IfcImport.GetLog())
|
||||||
txt.from_string(IfcImport.GetLog())
|
|
||||||
|
|
||||||
IfcImport.CleanUp()
|
IfcImport.CleanUp()
|
||||||
|
|
||||||
@@ -253,13 +220,7 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
|
|||||||
default=False)
|
default=False)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
global wrong_unicode
|
if not import_ifc(self.filepath, self.use_names, self.process_relations):
|
||||||
if wrong_unicode and sys.platform[0:5] != 'linux':
|
|
||||||
self.report({'ERROR'},
|
|
||||||
'Your version of Blender is incompatible with IfcBlender\n' \
|
|
||||||
'Please use the offical release from http://blender.org instead'
|
|
||||||
)
|
|
||||||
elif not import_ifc(self.filepath, self.use_names, self.process_relations):
|
|
||||||
self.report({'ERROR'},
|
self.report({'ERROR'},
|
||||||
'Unable to parse .ifc file or no geometrical entities found'
|
'Unable to parse .ifc file or no geometrical entities found'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ int main ( int argc, char** argv ) {
|
|||||||
std::cout << "Creating geometry..." << std::endl;
|
std::cout << "Creating geometry..." << std::endl;
|
||||||
|
|
||||||
// The functions IfcGeomObjects::Get() and IfcGeomObjects::Next() wrap an iterator of all geometrical entities in the Ifc file.
|
// The functions IfcGeomObjects::Get() and IfcGeomObjects::Next() wrap an iterator of all geometrical entities in the Ifc file.
|
||||||
// IfcGeomObjects::Get() returns an IfcGeomObjects::IfcGeomObject (see IfcObjects.h for definition)
|
// IfcGeomObjects::Get() returns an IfcGeomObjects::IfcGeomObject (see IfcGeomObjects.h for definition)
|
||||||
// IfcGeomObjects::Next() is used to poll whether more geometrical entities are available
|
// IfcGeomObjects::Next() is used to poll whether more geometrical entities are available
|
||||||
int vcount_total = 1;
|
int vcount_total = 1;
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -34,9 +34,9 @@
|
|||||||
// loads a file on disk into multiple chunks, has been disabled.
|
// loads a file on disk into multiple chunks, has been disabled.
|
||||||
// It proved to be an inefficient way of working with large files,
|
// It proved to be an inefficient way of working with large files,
|
||||||
// as often these did not facilitate to be parsed in a sequential
|
// as often these did not facilitate to be parsed in a sequential
|
||||||
// manner efficiently, to enable the paging functionality uncomment
|
// manner efficiently. To enable the paging functionality uncomment
|
||||||
// the following statement.
|
// the following statement.
|
||||||
//const int BUF_SIZE = (128 * 1024 * 1024);
|
// #define BUF_SIZE (8 * 1024 * 1024)
|
||||||
|
|
||||||
namespace IfcParse {
|
namespace IfcParse {
|
||||||
/// The IfcSpfStream class represents a ISO 10303-21 IFC-SPF file in memory.
|
/// The IfcSpfStream class represents a ISO 10303-21 IFC-SPF file in memory.
|
||||||
@@ -48,7 +48,7 @@ namespace IfcParse {
|
|||||||
/// detrimental for the performance of the parser.
|
/// detrimental for the performance of the parser.
|
||||||
class IfcSpfStream {
|
class IfcSpfStream {
|
||||||
private:
|
private:
|
||||||
std::ifstream stream;
|
FILE* stream;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
unsigned int ptr;
|
unsigned int ptr;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
|||||||
+31
-19
@@ -23,6 +23,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../ifcparse/IfcCharacterDecoder.h"
|
#include "../ifcparse/IfcCharacterDecoder.h"
|
||||||
#include "../ifcparse/IfcParse.h"
|
#include "../ifcparse/IfcParse.h"
|
||||||
#include "../ifcparse/IfcException.h"
|
#include "../ifcparse/IfcException.h"
|
||||||
@@ -37,15 +41,23 @@ using namespace IfcParse;
|
|||||||
//
|
//
|
||||||
IfcSpfStream::IfcSpfStream(const std::string& fn) {
|
IfcSpfStream::IfcSpfStream(const std::string& fn) {
|
||||||
eof = false;
|
eof = false;
|
||||||
stream.open(fn.c_str(),std::ios_base::binary);
|
#ifdef _MSC_VER
|
||||||
if ( ! stream.good() ) {
|
int fn_buffer_size = MultiByteToWideChar(CP_UTF8, 0, fn.c_str(), -1, 0, 0);
|
||||||
|
wchar_t* fn_wide = new wchar_t[fn_buffer_size];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, fn.c_str(), -1, fn_wide, fn_buffer_size);
|
||||||
|
stream = _wfopen(fn_wide, L"rb");
|
||||||
|
delete[] fn_wide;
|
||||||
|
#else
|
||||||
|
stream = fopen(fn.c_str(), "rb");
|
||||||
|
#endif
|
||||||
|
if (stream == NULL) {
|
||||||
valid = false;
|
valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
valid = true;
|
valid = true;
|
||||||
stream.seekg(0,std::ios_base::end);
|
fseek(stream, 0, SEEK_END);
|
||||||
size = (unsigned int) stream.tellg();
|
size = (unsigned int) ftell(stream);;
|
||||||
stream.seekg(0,std::ios_base::beg);
|
rewind(stream);
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
offset = 0;
|
offset = 0;
|
||||||
paging = size > BUF_SIZE;
|
paging = size > BUF_SIZE;
|
||||||
@@ -87,7 +99,7 @@ IfcSpfStream::IfcSpfStream(void* data, int l) {
|
|||||||
|
|
||||||
void IfcSpfStream::Close() {
|
void IfcSpfStream::Close() {
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
if ( paging ) stream.close();
|
if ( paging ) fclose(stream);
|
||||||
#endif
|
#endif
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
@@ -96,26 +108,26 @@ void IfcSpfStream::Close() {
|
|||||||
// Reads a chunk of BUF_SIZE in memory and increments cursor if requested
|
// Reads a chunk of BUF_SIZE in memory and increments cursor if requested
|
||||||
//
|
//
|
||||||
void IfcSpfStream::ReadBuffer(bool inc) {
|
void IfcSpfStream::ReadBuffer(bool inc) {
|
||||||
|
std::cout << "Readbuffer" << std::endl;
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
if ( inc ) {
|
if ( inc ) {
|
||||||
offset += len;
|
offset += len;
|
||||||
stream.seekg(offset,std::ios_base::beg);
|
fseek(stream, offset, SEEK_SET);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
eof = stream.eof();
|
eof = feof(stream) != 0;
|
||||||
if ( eof ) return;
|
if ( eof ) return;
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
stream.read(buffer,size < BUF_SIZE ? size : BUF_SIZE);
|
len = (unsigned int) fread(buffer, 1, size < BUF_SIZE ? size : BUF_SIZE, stream);
|
||||||
#else
|
#else
|
||||||
stream.read(buffer,size);
|
len = (unsigned int) fread(buffer, 1, size, stream);
|
||||||
#endif
|
#endif
|
||||||
len = (unsigned int) stream.gcount();
|
|
||||||
eof = len == 0;
|
eof = len == 0;
|
||||||
ptr = 0;
|
ptr = 0;
|
||||||
#ifdef BUF_SIZE
|
#ifdef BUF_SIZE
|
||||||
if (!paging) stream.close();
|
if (!paging) fclose(stream);
|
||||||
#else
|
#else
|
||||||
stream.close();
|
fclose(stream);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,8 +146,8 @@ void IfcSpfStream::Seek(unsigned int o) {
|
|||||||
ptr = o - offset;
|
ptr = o - offset;
|
||||||
} else {
|
} else {
|
||||||
offset = o;
|
offset = o;
|
||||||
stream.clear();
|
clearerr(stream);
|
||||||
stream.seekg(o,std::ios_base::beg);
|
fseek(stream, o, SEEK_SET);
|
||||||
ReadBuffer(false);
|
ReadBuffer(false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -160,9 +172,9 @@ char IfcSpfStream::Read(unsigned int o) {
|
|||||||
} else if ( o >= offset && (o < (offset+len)) ) {
|
} else if ( o >= offset && (o < (offset+len)) ) {
|
||||||
return buffer[o-offset];
|
return buffer[o-offset];
|
||||||
} else {
|
} else {
|
||||||
stream.clear();
|
clearerr(stream);
|
||||||
stream.seekg(o,std::ios_base::beg);
|
fseek(stream, o, SEEK_SET);
|
||||||
return stream.peek();
|
return ungetc(getc(stream), stream);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -719,7 +731,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
|||||||
Logger::Message(Logger::LOG_WARNING,ss.str());
|
Logger::Message(Logger::LOG_WARNING,ss.str());
|
||||||
}
|
}
|
||||||
byid[currentId] = entity;
|
byid[currentId] = entity;
|
||||||
MaxId = std::max(MaxId,currentId);
|
MaxId = (std::max)(MaxId,currentId);
|
||||||
currentId = 0;
|
currentId = 0;
|
||||||
} else {
|
} else {
|
||||||
try { token = tokens->Next(); }
|
try { token = tokens->Next(); }
|
||||||
|
|||||||
@@ -46,21 +46,6 @@ namespace IfcGeomObjects {
|
|||||||
std::string type;
|
std::string type;
|
||||||
std::string guid;
|
std::string guid;
|
||||||
std::vector<float> matrix;
|
std::vector<float> matrix;
|
||||||
const std::vector<int> name_as_intvector() {
|
|
||||||
std::vector<int> r;
|
|
||||||
for ( std::string::const_iterator it = name.begin(); it != name.end(); ++ it ) r.push_back(*it);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
const std::vector<int> type_as_intvector() {
|
|
||||||
std::vector<int> r;
|
|
||||||
for ( std::string::const_iterator it = type.begin(); it != type.end(); ++ it ) r.push_back(*it);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
const std::vector<int> guid_as_intvector() {
|
|
||||||
std::vector<int> r;
|
|
||||||
for ( std::string::const_iterator it = guid.begin(); it != guid.end(); ++ it ) r.push_back(*it);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IfcGeomObject : public IfcObject {
|
class IfcGeomObject : public IfcObject {
|
||||||
@@ -71,13 +56,9 @@ namespace IfcGeomObjects {
|
|||||||
bool Next();
|
bool Next();
|
||||||
const IfcGeomObject* Get();
|
const IfcGeomObject* Get();
|
||||||
bool Init(const std::string fn);
|
bool Init(const std::string fn);
|
||||||
bool InitUCS2(const char* fn) {
|
|
||||||
return Init(std::string(fn+1));
|
|
||||||
}
|
|
||||||
void Settings(int setting, bool value);
|
void Settings(int setting, bool value);
|
||||||
int Progress();
|
int Progress();
|
||||||
const IfcObject* GetObject(int id);
|
const IfcObject* GetObject(int id);
|
||||||
bool CleanUp();
|
bool CleanUp();
|
||||||
std::string GetLog();
|
std::string GetLog();
|
||||||
|
|
||||||
};
|
};
|
||||||
+2
-1
@@ -63,7 +63,8 @@ scn.render.resolution_x = 2048
|
|||||||
scn.render.resolution_y = 2048
|
scn.render.resolution_y = 2048
|
||||||
scn.world.horizon_color = (1,1,1)
|
scn.world.horizon_color = (1,1,1)
|
||||||
scn.world.ambient_color = (0.05,0.05,0.05)
|
scn.world.ambient_color = (0.05,0.05,0.05)
|
||||||
scn.render.color_mode = 'RGBA'
|
try: scn.render.color_mode = 'RGBA'
|
||||||
|
except: scn.render.image_settings.color_mode = 'RGBA'
|
||||||
|
|
||||||
for m in bpy.data.materials: m.specular_intensity = 0
|
for m in bpy.data.materials: m.specular_intensity = 0
|
||||||
def material(name,settings):
|
def material(name,settings):
|
||||||
|
|||||||
Reference in New Issue
Block a user