Dynamicly drawing polygon with Primitive API by mouse click throws error

1. A concise explanation of the problem you’re experiencing.
I want to draw polygon dynamicly. The code below works fine when i add a static polygon primitive to the scene.

          var viewer = new Cesium.Viewer('cesiumContainer');
          var geometry = new Cesium.PolygonGeometry({
    		 polygonHierarchy : new Cesium.PolygonHierarchy(
    			Cesium.Cartesian3.fromDegreesArray([
                                    -109.080842,45.002073,  
                                   -105.91517,45.002073,  
                                   -104.058488,44.996596,  
                                    -104.053011,43.002989,  
                                 -104.053011,41.003906,  
                                  -105.728954,40.998429,  
                                  -107.919731,41.003906,  
                                  -109.04798,40.998429,  
                               -111.047063,40.998429,  
                                   -111.047063,42.000709,  
                                  -111.047063,44.476286,  
                                  -111.05254,45.002073])
    		  )
    		});
    		var instance = new Cesium.GeometryInstance({
    			geometry:geometry,
    			attributes : {
    				color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.WHITE.withAlpha(0.5))
    			}
    		});
    		viewer.scene.primitives.add(new Cesium.GroundPrimitive({
    			geometryInstances : instance,
    			appearance : new Cesium.PerInstanceColorAppearance()
    		}));

But when I transplant it to the dynamic scene, it throws error:

2. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.

    var viewer = new Cesium.Viewer('cesiumContainer');
    viewer.scene.globe.depthTestAgainstTerrain = true;
    var activeShapePoints = [];	
    var activeShape;
     var floatingPoint;

        function createPoint(worldPosition) {
            var point = viewer.entities.add({
            	name:'point',
                   position: worldPosition,
                point: {
                    color: Cesium.Color.WHITE,
                    pixelSize: 8,
                    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
                }
            });
            return point;
        }
     
        function drawShape(positionData) {      
    			var geometry = new Cesium.PolygonGeometry({
    				polygonHierarchy : new Cesium.PolygonHierarchy(positionData)
    			});
    			
    			var instance = new Cesium.GeometryInstance({
    			  geometry : geometry,			
    			  attributes : {
    				color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.WHITE.withAlpha(0.5))
    			  }
    			});
    			var shape = viewer.scene.primitives.add(new Cesium.GroundPrimitive({
    			  geometryInstances : instance			  
    			}));
    			
            return shape;
        }       
       
        function terminateShape() {			
            activeShapePoints.pop(); 
            if (activeShapePoints.length) {
    				drawShape(activeShapePoints); 
            }
            viewer.entities.remove(floatingPoint);
            viewer.entities.remove(activeShape); 
            floatingPoint = undefined;
            activeShape = undefined;
            activeShapePoints = [];    			
        }

    	 var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
        handler.setInputAction(function (event) {            
            var earthPosition = viewer.scene.pickPosition(event.position);
            if (Cesium.defined(earthPosition)) {            
    				if (activeShapePoints.length === 0) {
                    floatingPoint = createPoint(earthPosition);
                    activeShapePoints.push(earthPosition);
                    var dynamicPositions = new Cesium.CallbackProperty(function () {    	                   
    			      return new Cesium.PolygonHierarchy(activeShapePoints);    			     
                    }, false);
                    activeShape = drawShape(dynamicPositions);
                }			
    				activeShapePoints.push(earthPosition);				
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        handler.setInputAction(function (event) {
            if (Cesium.defined(floatingPoint)) {
                var newPosition = viewer.scene.pickPosition(event.endPosition);
                if (Cesium.defined(newPosition)) {
                    floatingPoint.position.setValue(newPosition);
                    activeShapePoints.pop();
                    activeShapePoints.push(newPosition);
                }
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        handler.setInputAction(function (event) {
              terminateShape();
        }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);		

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.
I want to dynamicly drawing polygon with Primitive API by mouse click.

4. The Cesium version you’re using, your operating system and browser.
Cesium1.68, Windows 7, Chrome

You’re getting this error because PolygonHierarchy does not take a callback property: https://cesium.com/docs/cesiumjs-ref-doc/PolygonHierarchy.html#PolygonHierarchy

Is there something you’re trying to do that can’t be done with the Entity API like in the code example here (https://sandcastle.cesium.com/index.html?src=Drawing%20on%20Terrain.html) ? Those polygons can be dynamic as well.

If you want have a “dynamic” set of positions with the primitive API, you’ll need to destroy the primitive and create a new one whenever the positions change.

As shown in the following figure, it need a long time to rendering the shape when redraw it with the Entity API. So I am wondering is the Primitive API’s performance is much higher than the Entity API, since the last one is built directly on top of the Primitive API.


On the other hand, I still don’t know how to fix the bug metioned above the topic, since the code example above you mentioned also use PolygonHierarchy, and its position param is also a callback function.

viewer.entities.add({
polygon: {
hierarchy: positionData,
material: new Cesium.ColorMaterialProperty(
Cesium.Color.WHITE.withAlpha(0.7)
),
},
});

The Entity API actually uses the Primitive API under the hood. In most cases you won’t see any performance difference. The reason you see the difference here is because the Entity API creates geometry asynchronously for static geometry to reduce the work done on the main thread.

When using the Primitive API there’s no notion of callback properties. You must pass in the position data directly as define in the documentation. See this guide on working with primitives: Custom Geometry & Appearances – Cesium