<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Auto-Created sections but Viewpoint not appearing in the Navigator in Archicad C++ API</title>
    <link>https://community.graphisoft.com/t5/Archicad-C-API/Auto-Created-sections-but-Viewpoint-not-appearing-in-the/m-p/645241#M10073</link>
    <description>&lt;P&gt;Hi everyone,&lt;/P&gt;&lt;P&gt;I’m trying to automate the creation of cut planes in front of ~200 doors, so that each door has its own section.&lt;BR /&gt;&lt;BR /&gt;I compute each door’s position and then create an API_CutPlaneType element for the cut line and marker. This part works. The marker shows in plan. But no section is added to the Navigator, and the marker is locked so I can’t manually convert it into a real section viewpoint.&lt;/P&gt;&lt;P&gt;Here’s my (messy) code : (Devikit 25)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="cpp"&gt;#include "APIEnvir.h"
#include "ACAPinc.h"
#include &amp;lt;cmath&amp;gt;
#pragma execution_character_set("utf-8")

static void WriteReport(const GS::UniString&amp;amp; message)
{
    ACAPI_WriteReport(message.ToCStr().Get(), false);
}

static GSErrCode ValidateDoors(void)
{
    GSErrCode err = NoError;

    GS::Array&amp;lt;API_Guid&amp;gt; doorGuids;
    err = ACAPI_Element_GetElemList(API_DoorID, &amp;amp;doorGuids);
    if (err != NoError) {
        WriteReport("Erreur lors de la récupération des GUIDs des portes.");
        return err;
    }

    WriteReport("Nombre de portes trouvées : " + GS::UniString::Printf("%d", doorGuids.GetSize()));

    Int32 doorIndex = 0;

    for (const auto&amp;amp; doorGuid : doorGuids) {
        API_Element doorElem{}, wallElem{};
        BNZeroMemory(&amp;amp;doorElem,  sizeof(API_Element));
        BNZeroMemory(&amp;amp;wallElem,  sizeof(API_Element));

        doorElem.header.guid = doorGuid;
        if (ACAPI_Element_Get(&amp;amp;doorElem) != NoError) {
            WriteReport("Erreur lors de la récupération de la porte.");
            continue;
        }
        wallElem.header.guid = doorElem.door.owner;
        if (ACAPI_Element_Get(&amp;amp;wallElem) != NoError) {
            WriteReport("Erreur lors de la récupération du mur parent.");
            continue;
        }

        // Points début/fin du mur
        API_Coord beg = wallElem.wall.begC;
        API_Coord end = wallElem.wall.endC;

        // Vecteur unitaire du mur
        API_Vector wallVec = {end.x - beg.x, end.y - beg.y};
        double vecLength = sqrt(wallVec.x * wallVec.x + wallVec.y * wallVec.y);
        if (vecLength &amp;lt; 1e-9) {
            WriteReport("Longueur mur invalide.");
            continue;
        }
        API_Vector wallUnitVec = {wallVec.x / vecLength, wallVec.y / vecLength};

        // Position porte
        double objLoc = doorElem.door.objLoc;
        API_Coord doorPos = {
            beg.x + wallUnitVec.x * objLoc,
            beg.y + wallUnitVec.y * objLoc
        };

        // Normale (perp. mur)
        API_Vector normVec = {-wallUnitVec.y, wallUnitVec.x};

        // Préparation de la coupe
        API_Element cutPlaneElem{};
        API_ElementMemo cutPlaneMemo{};
        API_SubElement cutPlaneMarker{};
        BNZeroMemory(&amp;amp;cutPlaneElem,    sizeof(API_Element));
        BNZeroMemory(&amp;amp;cutPlaneMemo,    sizeof(API_ElementMemo));
        BNZeroMemory(&amp;amp;cutPlaneMarker,  sizeof(API_SubElement));

        // Type coupe
        cutPlaneElem.header.typeID = API_CutPlaneID;
        // Important : copier l’étage
        cutPlaneElem.header.floorInd = doorElem.header.floorInd;
        cutPlaneMarker.subType       = APISubElement_MainMarker;

        // Récup. des defaults
        err = ACAPI_Element_GetDefaultsExt(&amp;amp;cutPlaneElem, &amp;amp;cutPlaneMemo, 1UL, &amp;amp;cutPlaneMarker);
        if (err != NoError) {
            WriteReport("Impossible de récupérer les defaults pour la coupe.");
            continue;
        }

        // Remplir manuellement quelques champs
        // (parfois nécessaires selon la configuration du template)
        cutPlaneElem.cutPlane.segment.segType = APISect_Normal;
        cutPlaneElem.cutPlane.segment.flags   = 0;
        cutPlaneElem.cutPlane.linkData.showOnHome = true;
        cutPlaneElem.cutPlane.linkData.refFloor   = doorElem.header.floorInd;
        cutPlaneElem.cutPlane.linkData.sourceMarker = true;

        // Nom unique
        GS::UniString coupeName = GS::UniString::Printf("Section_Porte_%d", ++doorIndex);
        GS::UniString coupeId   = GS::UniString::Printf("ID_Porte_%d", doorIndex);

        GS::ucscpy(cutPlaneElem.cutPlane.segment.cutPlName, coupeName.ToUStr());
        GS::ucscpy(cutPlaneElem.cutPlane.segment.cutPlIdStr, coupeId.ToUStr());

        // Points "main coords" (ligne de coupe)
        double halfLength = 0.5;
        API_Coord startCoord, endCoord;
        startCoord.x = doorPos.x - halfLength * normVec.x;
        startCoord.y = doorPos.y - halfLength * normVec.y;
        endCoord.x   = doorPos.x + halfLength * normVec.x;
        endCoord.y   = doorPos.y + halfLength * normVec.y;

        cutPlaneMemo.sectionSegmentMainCoords = (API_Coord*) BMAllocatePtr(2 * sizeof(API_Coord), ALLOCATE_CLEAR, 0);
        if (cutPlaneMemo.sectionSegmentMainCoords == nullptr) {
            WriteReport("Erreur d'allocation memo mainCoords.");
            ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMemo);
            ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMarker.memo);
            continue;
        }
        cutPlaneMemo.sectionSegmentMainCoords[0] = startCoord;
        cutPlaneMemo.sectionSegmentMainCoords[1] = endCoord;

        cutPlaneElem.cutPlane.segment.nMainCoord  = 2;
        cutPlaneElem.cutPlane.segment.nDepthCoord = 2;

        // Rotation manuelle à 90° pour la profondeur
        double dx = endCoord.x - startCoord.x;
        double dy = endCoord.y - startCoord.y;

        // Tourner de 90° autour de startCoord
        API_Coord rotCoord;
        rotCoord.x = startCoord.x - dy;
        rotCoord.y = startCoord.y + dx;

        // Vecteur unitaire
        API_Vector v;
        v.x = rotCoord.x - startCoord.x;
        v.y = rotCoord.y - startCoord.y;
        double len = sqrt(v.x*v.x + v.y*v.y);
        if (len &amp;lt; 1e-9)
            len = 1.0; // éviter division par 0
        v.x /= len;
        v.y /= len;

        // Points de profondeur
        cutPlaneMemo.sectionSegmentDepthCoords = (API_Coord*) BMAllocatePtr(2 * sizeof(API_Coord), ALLOCATE_CLEAR, 0);
        if (cutPlaneMemo.sectionSegmentDepthCoords == nullptr) {
            WriteReport("Erreur alloc memo depthCoords.");
            ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMemo);
            ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMarker.memo);
            continue;
        }
        API_Coord refCoord, deeperCoord;
        refCoord.x = startCoord.x + v.x;
        refCoord.y = startCoord.y + v.y;
        deeperCoord.x = refCoord.x + v.x;
        deeperCoord.y = refCoord.y + v.y;

        cutPlaneMemo.sectionSegmentDepthCoords[0] = refCoord;
        cutPlaneMemo.sectionSegmentDepthCoords[1] = deeperCoord;

        // Création enveloppée dans une Undoable Command :
        err = ACAPI_CallUndoableCommand("Create Section for Door", [&amp;amp;]() -&amp;gt; GSErrCode {
            return ACAPI_Element_CreateExt(&amp;amp;cutPlaneElem, &amp;amp;cutPlaneMemo, 1UL, &amp;amp;cutPlaneMarker);
        });

        if (err == NoError) {
            WriteReport("Coupe créée avec succès : " + coupeName);
        } else {
            WriteReport("Erreur lors de la création de la coupe pour la porte " 
                        + GS::UniString::Printf("%d", doorIndex));
        }

        // Libération
        ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMemo);
        ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMarker.memo);
    }

    WriteReport("Validation des portes terminée.");
    return NoError;
}

static GSErrCode __ACENV_CALL MenuCommandHandler(const API_MenuParams* menuParams)
{
    WriteReport("Menu sélectionné : Validation des portes + création de coupes.");
    return ValidateDoors();
}

GSErrCode __ACDLL_CALL RegisterInterface(void)
{
    return ACAPI_Register_Menu(32500, 32501, MenuCode_UserDef, MenuFlag_Default);
}

API_AddonType __ACDLL_CALL CheckEnvironment(API_EnvirParams* envir)
{
    envir-&amp;gt;addOnInfo.description = "Valider les données des portes et créer des coupes";
    return APIAddon_Normal;
}

GSErrCode __ACDLL_CALL Initialize(void)
{
    GSErrCode err = NoError;
    err = ACAPI_Install_MenuHandler(32500, MenuCommandHandler);
    if (err != NoError) {
        WriteReport("Erreur lors de l'installation du gestionnaire de menu.");
    }
    return err;
}

GSErrCode __ACDLL_CALL FreeData(void)
{
    return NoError;
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I must be missing something. The line is drawn, but I don’t see any new section in the Navigator. Has anyone successfully done this? Any help or guidance would be greatly appreciated!&lt;/P&gt;&lt;P&gt;Thanks!&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
    <pubDate>Tue, 07 Jan 2025 01:03:09 GMT</pubDate>
    <dc:creator>Spacejoe</dc:creator>
    <dc:date>2025-01-07T01:03:09Z</dc:date>
    <item>
      <title>Auto-Created sections but Viewpoint not appearing in the Navigator</title>
      <link>https://community.graphisoft.com/t5/Archicad-C-API/Auto-Created-sections-but-Viewpoint-not-appearing-in-the/m-p/645241#M10073</link>
      <description>&lt;P&gt;Hi everyone,&lt;/P&gt;&lt;P&gt;I’m trying to automate the creation of cut planes in front of ~200 doors, so that each door has its own section.&lt;BR /&gt;&lt;BR /&gt;I compute each door’s position and then create an API_CutPlaneType element for the cut line and marker. This part works. The marker shows in plan. But no section is added to the Navigator, and the marker is locked so I can’t manually convert it into a real section viewpoint.&lt;/P&gt;&lt;P&gt;Here’s my (messy) code : (Devikit 25)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="cpp"&gt;#include "APIEnvir.h"
#include "ACAPinc.h"
#include &amp;lt;cmath&amp;gt;
#pragma execution_character_set("utf-8")

static void WriteReport(const GS::UniString&amp;amp; message)
{
    ACAPI_WriteReport(message.ToCStr().Get(), false);
}

static GSErrCode ValidateDoors(void)
{
    GSErrCode err = NoError;

    GS::Array&amp;lt;API_Guid&amp;gt; doorGuids;
    err = ACAPI_Element_GetElemList(API_DoorID, &amp;amp;doorGuids);
    if (err != NoError) {
        WriteReport("Erreur lors de la récupération des GUIDs des portes.");
        return err;
    }

    WriteReport("Nombre de portes trouvées : " + GS::UniString::Printf("%d", doorGuids.GetSize()));

    Int32 doorIndex = 0;

    for (const auto&amp;amp; doorGuid : doorGuids) {
        API_Element doorElem{}, wallElem{};
        BNZeroMemory(&amp;amp;doorElem,  sizeof(API_Element));
        BNZeroMemory(&amp;amp;wallElem,  sizeof(API_Element));

        doorElem.header.guid = doorGuid;
        if (ACAPI_Element_Get(&amp;amp;doorElem) != NoError) {
            WriteReport("Erreur lors de la récupération de la porte.");
            continue;
        }
        wallElem.header.guid = doorElem.door.owner;
        if (ACAPI_Element_Get(&amp;amp;wallElem) != NoError) {
            WriteReport("Erreur lors de la récupération du mur parent.");
            continue;
        }

        // Points début/fin du mur
        API_Coord beg = wallElem.wall.begC;
        API_Coord end = wallElem.wall.endC;

        // Vecteur unitaire du mur
        API_Vector wallVec = {end.x - beg.x, end.y - beg.y};
        double vecLength = sqrt(wallVec.x * wallVec.x + wallVec.y * wallVec.y);
        if (vecLength &amp;lt; 1e-9) {
            WriteReport("Longueur mur invalide.");
            continue;
        }
        API_Vector wallUnitVec = {wallVec.x / vecLength, wallVec.y / vecLength};

        // Position porte
        double objLoc = doorElem.door.objLoc;
        API_Coord doorPos = {
            beg.x + wallUnitVec.x * objLoc,
            beg.y + wallUnitVec.y * objLoc
        };

        // Normale (perp. mur)
        API_Vector normVec = {-wallUnitVec.y, wallUnitVec.x};

        // Préparation de la coupe
        API_Element cutPlaneElem{};
        API_ElementMemo cutPlaneMemo{};
        API_SubElement cutPlaneMarker{};
        BNZeroMemory(&amp;amp;cutPlaneElem,    sizeof(API_Element));
        BNZeroMemory(&amp;amp;cutPlaneMemo,    sizeof(API_ElementMemo));
        BNZeroMemory(&amp;amp;cutPlaneMarker,  sizeof(API_SubElement));

        // Type coupe
        cutPlaneElem.header.typeID = API_CutPlaneID;
        // Important : copier l’étage
        cutPlaneElem.header.floorInd = doorElem.header.floorInd;
        cutPlaneMarker.subType       = APISubElement_MainMarker;

        // Récup. des defaults
        err = ACAPI_Element_GetDefaultsExt(&amp;amp;cutPlaneElem, &amp;amp;cutPlaneMemo, 1UL, &amp;amp;cutPlaneMarker);
        if (err != NoError) {
            WriteReport("Impossible de récupérer les defaults pour la coupe.");
            continue;
        }

        // Remplir manuellement quelques champs
        // (parfois nécessaires selon la configuration du template)
        cutPlaneElem.cutPlane.segment.segType = APISect_Normal;
        cutPlaneElem.cutPlane.segment.flags   = 0;
        cutPlaneElem.cutPlane.linkData.showOnHome = true;
        cutPlaneElem.cutPlane.linkData.refFloor   = doorElem.header.floorInd;
        cutPlaneElem.cutPlane.linkData.sourceMarker = true;

        // Nom unique
        GS::UniString coupeName = GS::UniString::Printf("Section_Porte_%d", ++doorIndex);
        GS::UniString coupeId   = GS::UniString::Printf("ID_Porte_%d", doorIndex);

        GS::ucscpy(cutPlaneElem.cutPlane.segment.cutPlName, coupeName.ToUStr());
        GS::ucscpy(cutPlaneElem.cutPlane.segment.cutPlIdStr, coupeId.ToUStr());

        // Points "main coords" (ligne de coupe)
        double halfLength = 0.5;
        API_Coord startCoord, endCoord;
        startCoord.x = doorPos.x - halfLength * normVec.x;
        startCoord.y = doorPos.y - halfLength * normVec.y;
        endCoord.x   = doorPos.x + halfLength * normVec.x;
        endCoord.y   = doorPos.y + halfLength * normVec.y;

        cutPlaneMemo.sectionSegmentMainCoords = (API_Coord*) BMAllocatePtr(2 * sizeof(API_Coord), ALLOCATE_CLEAR, 0);
        if (cutPlaneMemo.sectionSegmentMainCoords == nullptr) {
            WriteReport("Erreur d'allocation memo mainCoords.");
            ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMemo);
            ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMarker.memo);
            continue;
        }
        cutPlaneMemo.sectionSegmentMainCoords[0] = startCoord;
        cutPlaneMemo.sectionSegmentMainCoords[1] = endCoord;

        cutPlaneElem.cutPlane.segment.nMainCoord  = 2;
        cutPlaneElem.cutPlane.segment.nDepthCoord = 2;

        // Rotation manuelle à 90° pour la profondeur
        double dx = endCoord.x - startCoord.x;
        double dy = endCoord.y - startCoord.y;

        // Tourner de 90° autour de startCoord
        API_Coord rotCoord;
        rotCoord.x = startCoord.x - dy;
        rotCoord.y = startCoord.y + dx;

        // Vecteur unitaire
        API_Vector v;
        v.x = rotCoord.x - startCoord.x;
        v.y = rotCoord.y - startCoord.y;
        double len = sqrt(v.x*v.x + v.y*v.y);
        if (len &amp;lt; 1e-9)
            len = 1.0; // éviter division par 0
        v.x /= len;
        v.y /= len;

        // Points de profondeur
        cutPlaneMemo.sectionSegmentDepthCoords = (API_Coord*) BMAllocatePtr(2 * sizeof(API_Coord), ALLOCATE_CLEAR, 0);
        if (cutPlaneMemo.sectionSegmentDepthCoords == nullptr) {
            WriteReport("Erreur alloc memo depthCoords.");
            ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMemo);
            ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMarker.memo);
            continue;
        }
        API_Coord refCoord, deeperCoord;
        refCoord.x = startCoord.x + v.x;
        refCoord.y = startCoord.y + v.y;
        deeperCoord.x = refCoord.x + v.x;
        deeperCoord.y = refCoord.y + v.y;

        cutPlaneMemo.sectionSegmentDepthCoords[0] = refCoord;
        cutPlaneMemo.sectionSegmentDepthCoords[1] = deeperCoord;

        // Création enveloppée dans une Undoable Command :
        err = ACAPI_CallUndoableCommand("Create Section for Door", [&amp;amp;]() -&amp;gt; GSErrCode {
            return ACAPI_Element_CreateExt(&amp;amp;cutPlaneElem, &amp;amp;cutPlaneMemo, 1UL, &amp;amp;cutPlaneMarker);
        });

        if (err == NoError) {
            WriteReport("Coupe créée avec succès : " + coupeName);
        } else {
            WriteReport("Erreur lors de la création de la coupe pour la porte " 
                        + GS::UniString::Printf("%d", doorIndex));
        }

        // Libération
        ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMemo);
        ACAPI_DisposeElemMemoHdls(&amp;amp;cutPlaneMarker.memo);
    }

    WriteReport("Validation des portes terminée.");
    return NoError;
}

static GSErrCode __ACENV_CALL MenuCommandHandler(const API_MenuParams* menuParams)
{
    WriteReport("Menu sélectionné : Validation des portes + création de coupes.");
    return ValidateDoors();
}

GSErrCode __ACDLL_CALL RegisterInterface(void)
{
    return ACAPI_Register_Menu(32500, 32501, MenuCode_UserDef, MenuFlag_Default);
}

API_AddonType __ACDLL_CALL CheckEnvironment(API_EnvirParams* envir)
{
    envir-&amp;gt;addOnInfo.description = "Valider les données des portes et créer des coupes";
    return APIAddon_Normal;
}

GSErrCode __ACDLL_CALL Initialize(void)
{
    GSErrCode err = NoError;
    err = ACAPI_Install_MenuHandler(32500, MenuCommandHandler);
    if (err != NoError) {
        WriteReport("Erreur lors de l'installation du gestionnaire de menu.");
    }
    return err;
}

GSErrCode __ACDLL_CALL FreeData(void)
{
    return NoError;
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I must be missing something. The line is drawn, but I don’t see any new section in the Navigator. Has anyone successfully done this? Any help or guidance would be greatly appreciated!&lt;/P&gt;&lt;P&gt;Thanks!&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 07 Jan 2025 01:03:09 GMT</pubDate>
      <guid>https://community.graphisoft.com/t5/Archicad-C-API/Auto-Created-sections-but-Viewpoint-not-appearing-in-the/m-p/645241#M10073</guid>
      <dc:creator>Spacejoe</dc:creator>
      <dc:date>2025-01-07T01:03:09Z</dc:date>
    </item>
  </channel>
</rss>

