How to use section planes in scenes

I am trying to use the new functionality of the C API, where it is now possible to define the active section plane of an entity.

So,

  • I have a wall with a scene whose camera is located above the wall.

  • I have defined a section plane which is parallel to the camera view, and cuts the wall at half its height.

  • I have added the section plane to the model’s entities

  • I have set this section plane to be the active section planes of the model’s entities

  • I have set the scene’s UseSectionPlanes variable to true

But still I don’t get the result I want: The scenes only shows me the top of the wall, without taking into account the section plane.

Any idea what could be wrong? Am I missing something?

Any help would be appreciated.

If everything else appears to be working correctly you may only need to reverse the normal vector.

enum SUResult SUPlane3DSetWithPointAndNormal(
    struct SUPlane3D* 	plane,
    const struct SUPoint3D* 	point,
    const struct SUVector3D* 	normal 
    )

Reversing the normal vector does not change anything. I keep digging, but everything seems ok to me… My section plane is definitely correct, and it is contained in the model’s entities.

Have you used this new functionality? May I see a code snippet of yours?

Did you set the scene page’s flags after both creating the plane and setting the property ?
I think this may be the equivalent of updating the scene page.

For information, see the Ruby API’s Sketchup::Page#update method doc.
It is the equivalent of manually clicking the update button in the GUI and checking the boxes on the popup.


Flags are listed here:
SketchUp C API: SketchUpAPI/model/scene.h File Reference

Setter function: SUSceneSetFlags()

Oh … another thing to check… be sure the model’s (or the page’s) RenderingOptions (if the page is using it’s own rendering options) has the DisplaySectionCuts set true.

I have tried both of your hints, but none of them changes anything.

I am using the Layout C API to define my layouts. In particular, I am using LODocumentAddEntity to add scene views into a document. Could it be that the problem comes from here?

The first thing to do is make sure that the model appears correctly in SketchUp.

Well that is the correct function to add a scene viewport (aka Layout::SketchUpModel object,) to the document.

Provided that it was created properly.

The style also has a setting flag for showing the section cuts.
A model scene can use either the model’s current active style, … or it’s own.

In addition, within LayOut, certain style options can be overridden for a viewport, or a different style (from the model’s styles collection) chosen. These overrides affect only that viewport and not other viewports or the model skp file.

Please upload one of the files you’ve created.

1 Like

Here you are.

Habran-Bercheux_M0-01_sub.skp (83.7 KB)

Okay I see it in the model, but it is pointing upwards. It needs to be reversed so it points downward.

The main issue with it not working for the top view is … that it is not set as the active section cut for that scene. In fact, it is not set as the active section cut in any of the scenes.

You said in the 1st post …

In the GUI (or the Ruby API) after a section is made active, the scene page must be updated with the FLAG_USE_SECTION_PLANES flag set.

So something is not working in the C API to update the scene page’s display properties (for section planes at least.)

At this point the C API gurus would need to see some pared down reproducible code.
The model need only be a cube or something simple.


Also have you fully read the main page for the C API and are properly initializing the C API ?

Now I have tried to duplicate the issue using the code shown below, and it crashes during the call to LODocumentExportToPDF…

All hard-coded numbers are coming from a bigger piece code and should be correct.
I also upload two files

1)“Habran-Bercheux_M0-01.skp” which is the basic model I use, without any section plane defined in it.

2)“Habran-Bercheux_M0-01_sub.skp” which is the model that I save after having defined a scene and a section plane in it.

Could you make sure the scene and the section plane are defined correctly in this model?
Then what could be the origin of the crash?

Thanks in advance,



#include <iostream>
#include <vector>

#include<SketchupAPI/initialize.h>
#include<SketchupAPI/sketchup.h>
#include <LayOutAPI/initialize.h>
#include <LayOutAPI/layout.h>

int main()
{
	SUInitialize();
	LOInitialize();

	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Importing model from .skp file
	//++++++++++++++++++++++++++++++++++++++++++++++++++++

	std::cout << "CREATE MODEL FROM FILE..." << std::endl;
	std::string file_path =
		"C://Users//regae//Documents//Paille_Tech//sketchup_api//skp_files//test//Habran-Bercheux_M0-01.skp";

	SUModelLoadStatus loadStatus = SUModelLoadStatus_Success;
	SUModelRef model = SU_INVALID;
	SUResult res = SUModelCreateFromFileWithStatus(&model, file_path.c_str(), &loadStatus);
	if (res != SU_ERROR_NONE) std::cout << "TEST 1 FAILED" << std::endl;

	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Create a scene and add it to the model
	//++++++++++++++++++++++++++++++++++++++++++++++++++++

	std::cout << "CREATE SCENE..." << std::endl;
	SUSceneRef scene = SU_INVALID;
	SUSceneCreate(&scene);
	std::string scene_name = "TOP_VIEW_SCENE";
	SUSceneSetName(scene, scene_name.c_str());
	int sceneIndex;
	res = SUModelAddScene(model, -1, scene, &sceneIndex);
	if (res != SU_ERROR_NONE) std::cout << "TEST 2 FAILED" << std::endl;
	sceneIndex++; //needed for LOSketchupModelSetCurrentScene

	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Create a camera and make the scene use it
	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	
	std::cout << "CREATE CAMERA..." << std::endl;
	SUCameraRef camera = SU_INVALID;
	SUCameraCreate(&camera);
	
	SUVector3D up; up.x = 0; up.y = -1; up.z = 0;
	SUPoint3D pos; pos.x = 263.307; pos.y = 9.921; pos.z = 114.724;
	SUPoint3D tg; tg.x = pos.x; tg.y = pos.y; tg.z = 0;
	SUCameraSetOrientation(camera, &pos, &tg, &up);
	SUCameraSetPerspective(camera, false);
	SUCameraSet2D(camera, true);
	SUCameraSetOrthographicFrustumHeight(camera, 21.1);

	res = SUSceneSetCamera(scene, camera);
	if (res != SU_ERROR_NONE) std::cout << "TEST 3 FAILED" << std::endl;
	SUSceneSetUseCamera(scene, true);

	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Create a section plane
	// Add it to the model's entities
	// Make it the model's active section plane
	// Make the scene use section planes 
	//++++++++++++++++++++++++++++++++++++++++++++++++++++

	std::cout << "CREATE SECTION PLANE..." << std::endl;
	SUPlane3D plane;
	SUPlane3DSetWithCoefficients(&plane, 0, 0, -1, 10);
	SUSectionPlaneRef sectionPlane = SU_INVALID;
	SUSectionPlaneCreate(&sectionPlane);
	SUSectionPlaneSetPlane(sectionPlane, &plane);
	std::string name = "top_scene_section";
	SUSectionPlaneSetName(sectionPlane, name.c_str());

	SUEntitiesRef entities = SU_INVALID;
	SUModelGetEntities(model, &entities);
	std::vector<SUSectionPlaneRef> planes;
	planes.push_back(sectionPlane);
	res = SUEntitiesAddSectionPlanes(entities, 1, &planes[0]);
	if (res != SU_ERROR_NONE) std::cout << "TEST 4 FAILED" << std::endl;
	res = SUEntitiesSetActiveSectionPlane(entities, sectionPlane);
	if (res != SU_ERROR_NONE) std::cout << "TEST 5 FAILED" << std::endl;

	SUSceneSetUseSectionPlanes(scene,true);

	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Save the model to another file
	// to be used in LODocument
	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	std::cout << "SAVING MODEL TO ANOTHER FILE..." << std::endl;
	std::string file_path2 =
		"C://Users//regae//Documents//Paille_Tech//sketchup_api//skp_files//test//Habran-Bercheux_M0-01_tmp.skp";

	SUModelVersion version = SUModelVersion_SU2021;
	res = SUModelSaveToFileWithVersion(model, file_path2.c_str(), version);
	if (res != SU_ERROR_NONE) std::cout << "TEST 6 FAILED" << std::endl;

	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Create an empty LODocument
	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	std::cout << "CREATE EMPTY DOCUMENT..." << std::endl;
	LODocumentRef document = SU_INVALID;
	LODocumentCreateEmpty(&document);

	LOLayerRef defaultLayer = SU_INVALID;
	LODocumentAddLayer(document, false /* shared */, &defaultLayer);
	LOLayerSetName(defaultLayer, "Default");

	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Create a LOSketchUpModel using the saved model
	//++++++++++++++++++++++++++++++++++++++++++++++++++++

	std::cout << "CREATE LOSKETCHUPMODEL FROM FILE..." << std::endl;
	LOSketchUpModelRef lomodel = SU_INVALID;
	LOAxisAlignedRect2D bounds;
	double INCH = 2.54;
	double margin = 1. / INCH;
	double page_x = 21. / INCH;
	double page_y = 29.7 / INCH;
	bounds.upper_left.x = margin;
	bounds.upper_left.y = margin;
	bounds.lower_right.x = page_x - margin;
	bounds.lower_right.y = page_y - margin;
	res = LOSketchUpModelCreate(&lomodel, file_path2.c_str(),&bounds);
	if (res != SU_ERROR_NONE) std::cout << "TEST 7 FAILED" << std::endl;

	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// add the scene view to the LODocument's first page
	//++++++++++++++++++++++++++++++++++++++++++++++++++++

	std::cout << "ADDING SCENE TO DOCUMENT..." << std::endl;
	LOPageRef page = SU_INVALID;
	LODocumentGetPageAtIndex(document, 0, &page);
	res = LOSketchUpModelSetCurrentScene(lomodel, sceneIndex);
	if (res != SU_ERROR_NONE) std::cout << "TEST 8 FAILED" << std::endl;
	LOEntityRef entity = LOSketchUpModelToEntity(lomodel);
	LODocumentAddEntity(document, entity, defaultLayer, page);

	bounds.upper_left.x = 1.814;
	bounds.upper_left.y = 7.898;
	bounds.lower_right.x = 6.454;
	bounds.lower_right.y = 11.595;
	double scale = 1. / 29.56;

	res = LOEntitySetUntransformedBounds(entity, &bounds);
	if (res != SU_ERROR_NONE) std::cout << "TEST 9 FAILED" << std::endl;
	res = LOSketchUpModelSetScale(lomodel, scale);
	if (res != SU_ERROR_NONE) std::cout << "TEST 10 FAILED" << std::endl;

	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Export LODocument to pdf and layout
	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	std::cout << "EXPORT RESULT IN PDF AND LAYOUT FORMATS..." << std::endl;
	std::string file_path_pdf =
		"C://Users//regae//Documents//Paille_Tech//sketchup_api//skp_files//test//Habran-Bercheux_M0-01.pdf";
	std::string file_path_lo =
		"C://Users//regae//Documents//Paille_Tech//sketchup_api//skp_files//test//Habran-Bercheux_M0-01.layout";

	LODictionaryRef dictionary = SU_INVALID;
	std::cout << "test A" << std::endl;
	LODocumentExportToPDF(document, file_path_pdf.c_str(), dictionary);
	std::cout << "test B" << std::endl;
	LODocumentSaveToFile(document, file_path_lo.c_str(), LODocumentVersion_Current);
	std::cout << "test C" << std::endl;


	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	// Terminate program
	//++++++++++++++++++++++++++++++++++++++++++++++++++++
	std::cout << "TERMINATE PROGRAM..." << std::endl;
	std::remove(file_path2.c_str());
	LODocumentRelease(&document);
	LOSketchUpModelRelease(&lomodel);
	SUModelRelease(&model);
	SUTerminate();
	LOTerminate();
}
```[Habran-Bercheux_M0-01.skp|attachment](upload://soFRZaxiCGvQFq9fT5xJFrfwwl0.skp) (87.0 KB)
[Habran-Bercheux_M0-01_tmp.skp|attachment](upload://z0nXbNupoHyEBpzLMSiY8qQwdcp.skp) (87.3 KB)

These files are not attached to the previous post, please edit and attach them.

Their definitions look correct, however …

It is best to mimic the SketchUp GUI. In order to update a scene page, it must be the active scene.
(You can restore the previous scene if you must.)

	SUSceneRef prev_scene = SU_INVALID;
	res = SUModelGetActiveScene(model, &prev_scene);
	if (res == SU_ERROR_NONE) std::cout << "PREVIOUS SCENE REFERENCED" << std::endl;

	res = SUModelSetActiveScene(model, scene);
	if (res == SU_ERROR_NONE) std::cout << "TOP SCENE ACTIVE" << std::endl;
 
	// Set the top scene to save and restore active section planes:
	res = SUSceneSetUseSectionPlanes(scene,true);
	if (res == SU_ERROR_NONE) std::cout << "TOP SCENE SET TO USE SECTION PLANES" << std::endl;

	// Set the model's active section plane:
	res = SUEntitiesSetActiveSectionPlane(entities, sectionPlane);
	if (res != SU_ERROR_NONE) std::cout << "TEST 5 FAILED" << std::endl;
	if (res == SU_ERROR_NONE) std::cout << "MODEL SECTION PLANE SET ACTIVE" << std::endl;

	// Update the top scene's flags:
	uint32_t flags = FLAG_USE_CAMERA | FLAG_USE_HIDDEN_OBJECTS | FLAG_USE_SECTION_PLANES;
	res = SUSceneSetFlags(scene, flags);
	if (res == SU_ERROR_NONE) std::cout << "TOP SCENE FLAGS SET" << std::endl;

	res = SUModelSetActiveScene(model, prev_scene);
	if (res == SU_ERROR_NONE) std::cout << "PREVIOUS SCENE ACTIVE" << std::endl;

Please concentrate this issue upon the scene / section plane problems.

Otherwise, just for FYI, the LO API is picky about the order in which things are done.
If you can attach C objects to the document or it’s collections before setting properties, then do it this way. (For example, you are setting the LOSketchUpModel's current scene before it is attached to the LO document. Add it to the document’s entities first, then set it’s active scene.)

Observations …
I do not see the document’s paper size being set. ( LODocumentGetPageInfo() / LOPageInfoRef )
Verify that the bounds of the model viewport fit the paper size.

I would say, try saving the LO document before attempting to export it to PDF.

A little off-topic, since I do not know so much about C API…

I do have different experience... :-)

You can update not only active, but selected scenes via GUI. I recently discovered it, please see here:

New elements automatically show in all scenes - #6 by dezmo

Yea, but in the C file API there is no GUI, and selecting an object from a collection in a GUI listing is a manual interface task.

When a scene is updated, what is current in the model view is used to update the scene.
But there is something a bit different happening when working just upon a file. There is no real view.

So the suggestion is to perhaps mimic as much as possible.

1 Like

Previous post re-edited with the files uploaded

My code looks like this now:

And I also upload the layout file that has been saved. I can’t open it myself. The pdf export still crashesHabran-Bercheux_M0-01.layout (75.5 KB)

	std::cout << "CREATE SECTION PLANE..." << std::endl;
	SUPlane3D plane;
	SUPlane3DSetWithCoefficients(&plane, 0, 0, -1, 10);
	SUSectionPlaneRef sectionPlane = SU_INVALID;
	SUSectionPlaneCreate(&sectionPlane);
	SUSectionPlaneSetPlane(sectionPlane, &plane);
	std::string name = "top_scene_section";
	SUSectionPlaneSetName(sectionPlane, name.c_str());

	SUEntitiesRef entities = SU_INVALID;
	SUModelGetEntities(model, &entities);
	std::vector<SUSectionPlaneRef> planes;
	planes.push_back(sectionPlane);
	res = SUEntitiesAddSectionPlanes(entities, 1, &planes[0]);
	if (res != SU_ERROR_NONE) std::cout << "TEST 4 FAILED" << std::endl;

	SUSceneRef prev_scene = SU_INVALID;
	SUModelGetActiveScene(model, &prev_scene);
	SUModelSetActiveScene(model, scene);
	SUSceneSetUseSectionPlanes(scene, true);

	res = SUEntitiesSetActiveSectionPlane(entities, sectionPlane);
	if (res != SU_ERROR_NONE) std::cout << "TEST 5 FAILED" << std::endl;

	uint32_t flags = FLAG_USE_CAMERA | FLAG_USE_HIDDEN_OBJECTS | FLAG_USE_SECTION_PLANES;
	SUSceneSetFlags(scene, flags);
	SUModelSetActiveScene(model, prev_scene);	

Have you inspected the return value of your calls to the SU and LO API? Whenever I’ve looked into such reports they are often a result of one call failing due to invalid input, but the application continues assuming everything is fine.

Well, getting back to my bigger application, I’ve tried to follow Dan’s tips.

Here are two pdf files which shows the result I get:

the “good” file shows the result I get without using any section plane, put by putting the top camera inside the wall and, given the LOSketchupModel corresponding to that scene, setting its render mode to Raster.

the “bad” file is what I get when trying to use a section plane and use it for the top scene. Very unexpectedly, the section planes applies to other scenes, but not the top scene!!

The difference in the code that has generated these two files is whether or not this line is commented:
SUModelSetActiveScene(model, topScene);

How is that even possible that this function call influences other scenes?

I’m verry sorry, but this new functionality seems atrociously messy.

new_assemblage_good.pdf (76.7 KB)
new_assemblage_bad.pdf (30.7 KB)

First you should validate that your function calls aren’t returning error values. Without asserting that all bets are off and it’s very hard to make guesses.

No file attachments are present, … yet.

It may be that scenes are initialized with all flag set as default.
So you may need to iterate the scenes collection and set the flags accordingly.

In which file is the top scene active?

Yes there are bugs in the APIs. This may be another.

The official bug tracker for both APIs is here: