nested_component_instance.skp (130.4 KB)
no_nested_component_instance.skp (124.9 KB)
CODE
#include <SketchUpAPI\sketchup.h>
#include <cstdio>
#include <assert.h>
#include <vector>
//\tSU[^(][^=]*\([^=]*\); 用于检查的正则
#define SU(api_function_call) {\
SUResult su_api_result = api_function_call;\
assert(SU_ERROR_NONE == su_api_result);\
}\
#define refute(condition) assert(!(condition))
SUResult MergeModel(SUModelRef src, SUModelRef* dest);
SUResult MergeEntities(SUModelRef src_model, SUModelRef *dest_model, SUEntitiesRef src_entities, SUEntitiesRef *dest_entities);
void FindComponentDefinition(SUModelRef model, SUComponentDefinitionRef def_from_other_model, SUComponentDefinitionRef * find_def);
void AddComponentDefinition(SUModelRef src_model, SUModelRef *dest_model, SUComponentDefinitionRef src_def, SUComponentDefinitionRef *res_def);
bool AddInstances(SUModelRef src_model, SUModelRef *dest_model, SUEntitiesRef src_entities, SUEntitiesRef * dest_entities);
bool AddFaces(SUEntitiesRef src_entities, SUGeometryInputRef geom_input_face, size_t *vertex_index);
bool AddEdges(SUEntitiesRef src_entities, SUGeometryInputRef geom_input_face, size_t *vertex_index);
void HandleLoop(SUGeometryInputRef geom_input, SULoopRef loop, SULoopInputRef input_loop, size_t *vertex_index);
size_t AddEdgeToGeomInput(SUEdgeRef src_edge, SUGeometryInputRef geom_input, size_t *vertex_index);
std::string sustr2str(SUStringRef str) {
size_t str_len = 0;
SUResult res = SUStringGetUTF8Length(str, &str_len);
if (res != SU_ERROR_NONE) return NULL;
char* str_char = new char[str_len + 1];
SUStringGetUTF8(str, str_len, str_char, &str_len);
if (res != SU_ERROR_NONE) {
delete[] str_char;
return NULL;
}
str_char[str_len] = '\0';
std::string string(str_char);
if (str_char) delete[] str_char;
return string;
}
SUStringRef str2sustr(std::string str) {
SUStringRef resstr = SU_INVALID;
SUResult res = SUStringCreateFromUTF8(&resstr, str.c_str());
if (res == SU_ERROR_NONE) return resstr;
return SU_INVALID;
}
int main() {
// Always initialize the API before using it
SUInitialize();
// Load the model from a file
SUResult res;
SUModelRef model1 = SU_INVALID, model2 = SU_INVALID;
res = SUModelCreateFromFile(&model1, "F:/no_nested_component_instance.skp");
if (res != SU_ERROR_NONE) {
printf("model1 open fail");
return res;
}
res = SUModelCreateFromFile(&model2,"F:/nested_component_instance.skp");
if (res != SU_ERROR_NONE) {
printf("model2 open fail");
return res;
}
MergeModel(model2, &model1);
SU(SUModelSaveToFile(model1, "F:/new.skp"));
SU(SUModelRelease(&model1));
// 因为复制后 会导致model2出错暂时取消该断言
SU(SUModelRelease(&model2));
SUTerminate();
return 0;
}
SUResult MergeModel(SUModelRef src, SUModelRef* dest) {
SUResult res;
SUEntitiesRef src_entities = SU_INVALID, dest_entities = SU_INVALID;
SU(SUModelGetEntities(src, &src_entities));
SU(SUModelGetEntities(*dest, &dest_entities));
MergeEntities(src, dest, src_entities, &dest_entities);
return SU_ERROR_NONE;
}
SUResult MergeEntities(SUModelRef src_model, SUModelRef *dest_model, SUEntitiesRef src_entities, SUEntitiesRef *dest_entities) {
SUEntityListRef src_list = SU_INVALID;
SUEntityListIteratorRef list_iterator = SU_INVALID;
SUGeometryInputRef geom_input = SU_INVALID;
SU(SUGeometryInputCreate(&geom_input));
size_t vertex_index = 0;
// 通过 geom_input 处理的内容 可以防止重复点 线
bool flag = AddFaces(src_entities, geom_input, &vertex_index);
flag = AddEdges(src_entities, geom_input, &vertex_index) | flag;
if (flag) SU(SUEntitiesFill(*dest_entities, geom_input, true));
SU(SUGeometryInputRelease(&geom_input));
AddInstances(src_model, dest_model, src_entities, dest_entities);
return SU_ERROR_NONE;
}
// model 中是否存在 src_def(来自于另一个model),如果不存在则添加
void FindComponentDefinition(SUModelRef model, SUComponentDefinitionRef def_from_other_model, SUComponentDefinitionRef * find_def)
{
SUStringRef guid_ref = SU_INVALID;
SU(SUStringCreate(&guid_ref));
SU(SUComponentDefinitionGetGuid(def_from_other_model, &guid_ref));
size_t num = 0;
SU(SUModelGetNumComponentDefinitions(model, &num));
if (num > 0) {
std::vector<SUComponentDefinitionRef> definitions(num);
SU(SUModelGetComponentDefinitions(model, num, &definitions[0], &num));
for (int i = 0; i < num; i++) {
SUStringRef guid_ref_temp = SU_INVALID;
SU(SUStringCreate(&guid_ref_temp));
SU(SUComponentDefinitionGetGuid(definitions[i], &guid_ref_temp));
int res = 0;
SU(SUStringCompare(guid_ref_temp, guid_ref, &res));
SU(SUStringRelease(&guid_ref_temp));
if (res == 0) { *find_def = definitions[i]; break; }
}
}
SU(SUStringRelease(&guid_ref));
}
// 添加定义体 如果定义体存在直接返回 不存在则添加后返回
void AddComponentDefinition(SUModelRef src_model, SUModelRef * dest_model, SUComponentDefinitionRef src_def, SUComponentDefinitionRef * res_def)
{
SUStringRef guid_ref = SU_INVALID;
SU(SUStringCreate(&guid_ref));
SU(SUComponentDefinitionGetGuid(src_def, &guid_ref));
FindComponentDefinition(*dest_model, src_def, res_def);
if (SUIsInvalid(*res_def)) {
SUComponentDefinitionCreate(res_def);
// 设置group name
SUStringRef name = SU_INVALID;
SU(SUStringCreate(&name));
SU(SUComponentDefinitionGetName(src_def, &name));
SU(SUComponentDefinitionSetName(*res_def, sustr2str(name).c_str()));
SU(SUStringRelease(&name));
SUStringRef description = SU_INVALID;
SU(SUStringCreate(&description));
SU(SUComponentDefinitionGetDescription(src_def, &description));
SU(SUComponentDefinitionSetDescription(*res_def, sustr2str(description).c_str()));
SU(SUStringRelease(&description));
SUComponentBehavior behavior;
SU(SUComponentDefinitionGetBehavior(src_def, &behavior));
SU(SUComponentDefinitionSetBehavior(*res_def, &behavior));
SUEntitiesRef src_entities = SU_INVALID, dest_entities = SU_INVALID;
SU(SUComponentDefinitionGetEntities(src_def, &src_entities));
SU(SUComponentDefinitionGetEntities(*res_def, &dest_entities));
MergeEntities(src_model, dest_model, src_entities, &dest_entities);
std::vector<SUComponentDefinitionRef> defs(1);
defs.push_back(*res_def);
SU(SUModelAddComponentDefinitions(*dest_model, defs.size(), &defs[0]));
SUStringRef guid = SU_INVALID;
SU(SUStringCreate(&guid));
SU(SUComponentDefinitionGetGuid(*res_def, &guid));
int res = 0;
SU(SUStringCompare(guid_ref, guid, &res));
SU(SUStringRelease(&guid));
}
SU(SUStringRelease(&guid_ref));
}
int fun_call_count = 0;
bool AddInstances(SUModelRef src_model, SUModelRef *dest_model, SUEntitiesRef src_entities, SUEntitiesRef * dest_entities)
{
size_t num = 0;
SU(SUEntitiesGetNumInstances(src_entities, &num));
if (num <= 0) return false;
std::vector<SUComponentInstanceRef> src_instances(num);
SU(SUEntitiesGetInstances(src_entities, num, &src_instances[0], &num));
fun_call_count++;
for (int i = 0; i < num; i++) {
SUComponentInstanceRef src_instance = src_instances[i];
SUComponentInstanceRef instance = SU_INVALID;
SUComponentDefinitionRef src_def = SU_INVALID;
SUComponentDefinitionRef dest_def = SU_INVALID;
SU(SUComponentInstanceGetDefinition(src_instance, &src_def));
AddComponentDefinition(src_model, dest_model, src_def, &dest_def);
if (SUIsInvalid(dest_def))
continue;
SUComponentDefinitionCreateInstance(dest_def, &instance);
// 设置transform
SUTransformation trans;
SU(SUComponentInstanceGetTransform(src_instance, &trans));
SU(SUComponentInstanceSetTransform(instance, &trans));
// 设置group name
SUStringRef name = SU_INVALID;
SU(SUStringCreate(&name));
SU(SUComponentInstanceGetName(src_instance, &name));
SU(SUComponentInstanceSetName(instance, sustr2str(name).c_str()));
SU(SUStringRelease(&name));
// 暂不处理嵌套组件
// if (fun_call_count == 1)
SU(SUEntitiesAddInstance(*dest_entities, instance, NULL));
}
fun_call_count--;
return true;
}
void HandleLoop(SUGeometryInputRef geom_input, SULoopRef loop, SULoopInputRef input_loop, size_t *vertex_index) {
size_t vertex_num = 0;
SU(SULoopGetNumVertices(loop, &vertex_num));
if (vertex_num < 2) return;
std::vector<SUVertexRef> loop_verts(vertex_num);
std::vector<SUPoint3D> loop_pts;
SU(SULoopGetVertices(loop, vertex_num, &loop_verts[0], &vertex_num));
for (size_t i = 0; i < vertex_num; i++) {
SUPoint3D pt;
SU(SUVertexGetPosition(loop_verts[i], &pt));
SU(SUGeometryInputAddVertex(geom_input, &pt));
SU(SULoopInputAddVertexIndex(input_loop, (*vertex_index) + i));
loop_pts.push_back(pt);
}
size_t edge_num = vertex_num, curve_s = -1;
std::vector<SUEdgeRef> edges(edge_num);
SUCurveRef curve = SU_INVALID;
SU(SULoopGetEdges(loop, edge_num, &edges[0], &edge_num));
for (size_t i = 0; i < edge_num; i++) {
// 处理面上弧线
if (SUEdgeGetCurve(edges[i], &curve) == SU_ERROR_NONE) {
if (curve_s == -1) curve_s = i;
}
else {
if (curve_s != -1 && (i - 1)>curve_s)
SU(SULoopInputAddCurve(input_loop, curve_s, (i - 1)));
curve_s = -1;
curve = SU_INVALID;
}
bool smoooth = false, soft = false, hidden = false;
SU(SUEdgeGetSmooth(edges[i], &smoooth));
SU(SULoopInputEdgeSetSmooth(input_loop, i, smoooth));
SU(SUEdgeGetSoft(edges[i], &soft));
SU(SULoopInputEdgeSetSoft(input_loop, i, soft));
SUDrawingElementRef element = SUEdgeToDrawingElement(edges[i]);
SU(SUDrawingElementGetHidden(element, &hidden));
SU(SULoopInputEdgeSetHidden(input_loop, i, hidden));
// 图层
/*SULayerRef layer = SU_INVALID;
SU(SUDrawingElementGetLayer(element, &layer));
SU(SULoopInputEdgeSetLayer(input_loop, i, layer));*/
}
// 整个loop都是弧线
if (curve_s != -1)
SU(SULoopInputAddCurve(input_loop, curve_s, (edge_num - 1)));
// 增加顶点数量
(*vertex_index) += vertex_num;
}
bool AddFaces(SUEntitiesRef src_entities, SUGeometryInputRef geom_input, size_t *vertex_index) {
size_t num = 0;
SU(SUEntitiesGetNumFaces(src_entities, &num));
if (num <= 0) return false;
std::vector<SUFaceRef> src_faces(num);
SU(SUEntitiesGetFaces(src_entities, num, &src_faces[0], &num));
for (int i = 0; i < num; i++) {
SUFaceRef src_face = src_faces[i];
SULoopRef out_loop = SU_INVALID;
SU(SUFaceGetOuterLoop(src_face, &out_loop));
size_t out_loop_length = 0;
SULoopInputRef outer_input_loop = SU_INVALID;
SU(SULoopInputCreate(&outer_input_loop));
HandleLoop(geom_input, out_loop, outer_input_loop, vertex_index);
// 创建外圈面
size_t added_face_index = -1;
SU(SUGeometryInputAddFace(geom_input, &outer_input_loop, &added_face_index));
//SU(SULoopInputRelease(&outer_input_loop));
// 创建内圈面
size_t inner_loops_length = 0;
SU(SUFaceGetNumInnerLoops(src_face, &inner_loops_length));
if (inner_loops_length != 0) {
std::vector<SULoopRef> inner_loops(inner_loops_length);
SU(SUFaceGetInnerLoops(src_face, inner_loops_length, &inner_loops[0], &inner_loops_length));
for (int i = 0; i < inner_loops_length; i++) {
SULoopInputRef inner_input_loop = SU_INVALID;
SU(SULoopInputCreate(&inner_input_loop));
HandleLoop(geom_input, out_loop, inner_input_loop, vertex_index);
// 添加内圈洞
SU(SUGeometryInputFaceAddInnerLoop(geom_input, added_face_index, &inner_input_loop));
}
}
}
return true;
}
size_t AddEdgeToGeomInput(SUEdgeRef src_edge, SUGeometryInputRef geom_input, size_t *vertex_index) {
SUVertexRef start = SU_INVALID, end = SU_INVALID;
SUPoint3D start_point_3d, end_point_3d;
size_t added_edge_index = 0;
SU(SUEdgeGetStartVertex(src_edge, &start));
SU(SUVertexGetPosition(start, &start_point_3d));
SU(SUGeometryInputAddVertex(geom_input, &start_point_3d));
SU(SUEdgeGetEndVertex(src_edge, &end));
SU(SUVertexGetPosition(end, &end_point_3d));
SU(SUGeometryInputAddVertex(geom_input, &end_point_3d));
SU(SUGeometryInputAddEdge(geom_input, (*vertex_index), (*vertex_index) + 1, &added_edge_index));
*vertex_index += 2;
// 柔化
bool smoooth = false, soft = false, hidden = false;
SU(SUEdgeGetSmooth(src_edge, &smoooth));
SU(SUEdgeGetSoft(src_edge, &soft));
SU(SUGeometryInputEdgeSetHidden(geom_input, added_edge_index, hidden));
SU(SUGeometryInputEdgeSetSoft(geom_input, added_edge_index, soft));
SU(SUGeometryInputEdgeSetSmooth(geom_input, added_edge_index, smoooth));
SUDrawingElementRef element = SUEdgeToDrawingElement(src_edge);
SU(SUDrawingElementGetHidden(element, &hidden));
SU(SUGeometryInputEdgeSetHidden(geom_input, added_edge_index, hidden));
return added_edge_index;
}
bool AddEdges(SUEntitiesRef src_entities, SUGeometryInputRef geom_input, size_t *vertex_index) {
size_t num = 0, handle_edge = 0;
SU(SUEntitiesGetNumEdges(src_entities, true, &num));
if (num <= 0) return false;
std::vector<SUEdgeRef> src_edges(num);
SU(SUEntitiesGetEdges(src_entities, true, num, &src_edges[0], &num));
for (int i = 0; i < num; i++) {
SUEdgeRef src_edge = src_edges[i];
// 跳过组成面的线
size_t face_num = 0;
SU(SUEdgeGetNumFaces(src_edge, &face_num));
if (face_num > 0) continue;
// 跳过组成弧线的线
SUCurveRef curve = SU_INVALID;
if (SUEdgeGetCurve(src_edge, &curve) == SU_ERROR_NONE) continue;
if (SUIsValid(curve)) continue;
handle_edge++;
AddEdgeToGeomInput(src_edge, geom_input, vertex_index);
}
return handle_edge > 0;
}