Пример #1
0
void ComboBox::Paint(Canvas& canvas, const Rect& dirty_rect) {

    __super::Paint(canvas, dirty_rect);

    float button_width = GetDropDownButtonWidth();
    auto button_rect = GetContentRect();
    button_rect.position.x = button_rect.position.x + button_rect.size.width - button_width;
    button_rect.size.width = button_width;

    float top_edge_length = button_width / 2;
    if (top_edge_length / 2 > button_rect.size.height / 2) {
        top_edge_length = button_rect.size.height / 2;
    }

    float height = top_edge_length / 2;
    float half_height = height / 2;
    Point center_point(
        button_rect.position.x + button_rect.size.width / 2,
        button_rect.position.y + button_rect.size.height / 2);

    Point left_point(center_point.x - height, center_point.y - half_height);
    left_point = MakeClearEdgePointForFill(left_point, ClearEdgeOption::Clear);

    Point right_point(center_point.x + height, center_point.y - half_height);
    right_point = MakeClearEdgePointForFill(right_point, ClearEdgeOption::Clear);

    Point bottom_point(center_point.x, center_point.y + half_height);
    bottom_point = MakeClearEdgePointForFill(bottom_point, ClearEdgeOption::Clear);

    auto path = GetApplication().GetResourceFactory()->CreatePathGeometry();
    if (path == nullptr) {
        return;
    }

    auto sink = path->Open();
    if (sink == nullptr) {
        return;
    }

    sink->BeginFigure(left_point, GeometrySink::BeginFigureOption::Fill);
    sink->AddLine(right_point);
    sink->AddLine(bottom_point);
    sink->EndFigure(GeometrySink::EndFigureOption::Close);
    sink->Close();

    Canvas::StateGuard state_guard(canvas);
    canvas.SetBrushWithColor(GetDropDownButtonColor());
    canvas.DrawGeometry(path);
}
// Reset all the values for the parcel in preparation for a sale
void LLFloaterAuction::doResetParcel()
{
	LLParcel* parcelp = mParcelp->getParcel();
	LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();

	if (parcelp
		&& region
		&& !mParcelUpdateCapUrl.empty())
	{
		LLSD body;
		std::string empty;

		// request new properties update from simulator
		U32 message_flags = 0x01;
		body["flags"] = ll_sd_from_U32(message_flags);

		// Set all the default parcel properties for auction
		body["local_id"] = parcelp->getLocalID();

		U32 parcel_flags = PF_ALLOW_LANDMARK |
						   PF_ALLOW_FLY	|
						   PF_CREATE_GROUP_OBJECTS |
						   PF_ALLOW_ALL_OBJECT_ENTRY |
						   PF_ALLOW_GROUP_OBJECT_ENTRY |
						   PF_ALLOW_GROUP_SCRIPTS |
						   PF_RESTRICT_PUSHOBJECT |
						   PF_SOUND_LOCAL |
						   PF_ALLOW_VOICE_CHAT |
						   PF_USE_ESTATE_VOICE_CHAN;

		body["parcel_flags"] = ll_sd_from_U32(parcel_flags);
		
		// Build a parcel name like "Ahern (128,128) PG 4032m"
		std::ostringstream parcel_name;
		LLVector3 center_point( parcelp->getCenterpoint() );
		center_point.snap(0);		// Get rid of fractions
		parcel_name << region->getName() 
					<< " ("
					<< (S32) center_point.mV[VX]
					<< ","
					<< (S32) center_point.mV[VY]						
					<< ") "
					<< region->getSimAccessString()
					<< " "
					<< parcelp->getArea()
					<< "m";

		std::string new_name(parcel_name.str().c_str());
		body["name"] = new_name;
		getChild<LLUICtrl>("parcel_text")->setValue(new_name);	// Set name in dialog as well, since it won't get updated otherwise

		body["sale_price"] = (S32) 0;
		body["description"] = empty;
		body["music_url"] = empty;
		body["media_url"] = empty;
		body["media_desc"] = empty;
		body["media_type"] = LLMIMETypes::getDefaultMimeType();
		body["media_width"] = (S32) 0;
		body["media_height"] = (S32) 0;
		body["auto_scale"] = (S32) 0;
		body["media_loop"] = (S32) 0;
		body["obscure_media"] = (S32) 0; // OBSOLETE - no longer used
		body["obscure_music"] = (S32) 0; // OBSOLETE - no longer used
		body["media_id"] = LLUUID::null;
		body["group_id"] = MAINTENANCE_GROUP_ID;	// Use maintenance group
		body["pass_price"] = (S32) 10;		// Defaults to $10
		body["pass_hours"] = 0.0f;
		body["category"] = (U8) LLParcel::C_NONE;
		body["auth_buyer_id"] = LLUUID::null;
		body["snapshot_id"] = LLUUID::null;
		body["user_location"] = ll_sd_from_vector3( LLVector3::zero );
		body["user_look_at"] = ll_sd_from_vector3( LLVector3::zero );
		body["landing_type"] = (U8) LLParcel::L_DIRECT;

		llinfos << "Sending parcel update to reset for auction via capability to: "
			<< mParcelUpdateCapUrl << llendl;
		LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::Responder());

		// Send a message to clear the object return time
		LLMessageSystem *msg = gMessageSystem;
		msg->newMessageFast(_PREHASH_ParcelSetOtherCleanTime);
		msg->nextBlockFast(_PREHASH_AgentData);
		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
		msg->nextBlockFast(_PREHASH_ParcelData);
		msg->addS32Fast(_PREHASH_LocalID, parcelp->getLocalID());
		msg->addS32Fast(_PREHASH_OtherCleanTime, 5);			// 5 minute object auto-return

		msg->sendReliable(region->getHost());

		// Clear the access lists
		clearParcelAccessLists(parcelp, region);
	}
}
Пример #3
0
CRhinoCommand::result CGenCylinder::RunCommand( const CRhinoCommandContext& context )
{

	Cscript1PlugIn& plugin = script1PlugIn();
	if( !plugin.IsDlgVisible() )
	{
		return CRhinoCommand::nothing;
	}

	/*****************************************/
	/*CHECKING IF THERE IS ALREADY A CYLINDER*/
	/*****************************************/
	const CRhinoLayer& layer = context.m_doc.m_layer_table.CurrentLayer();
	ON_SimpleArray<CRhinoObject*> objects;
	int object_count = context.m_doc.LookupObject( layer, objects );
	const CRhinoBrepObject* brep_obj;
	const CRhinoCurveObject* curve_obj;
	const CRhinoSurfaceObject* surface_obj;
	int surf_count=0;
	if( object_count > 0 )
	{
		int brep_obj_count = 0;
		int polycurve_count = 0;
		const CRhinoObject* object = 0;
		for(int i = 0; i < object_count; i++ )
		{
			object = objects[ i ];
			/************************************/
			/*TRY CASTING AS A RHINO BREP OBJECT*/ 
			/************************************/
			brep_obj = CRhinoBrepObject::Cast( object );
			if( brep_obj && object->IsSolid())
			{
				brep_obj_count++;
			}
			/*******************************/
			/*TRY CASTING AS A CURVE OBJECT*/ 
			/*******************************/
			curve_obj = CRhinoCurveObject::Cast( object );
			if( curve_obj )
			{
				polycurve_count++;
			}
			//surface_obj = CRhinoSurfaceObject::Cast( object );
		 //   if( surface_obj )
		 //   {
			//surf_count++;
		 //   }
		}
		if( brep_obj_count == 0)
		{
			ON_3dPoint center_point( 0.0, 0.0, 0.0 );
			double radius = 63.5;
			int __count = plugin.m_dialog->m_comboAltTacco.GetCount();

			int nIndex = plugin.m_dialog->m_comboAltTacco.GetCurSel();
			CString strCBText;
			plugin.m_dialog->m_comboAltTacco.GetLBText( nIndex, strCBText);
			int height = _wtoi(strCBText);


			ON_3dPoint height_point( 0.0, 0.0, height);
			ON_3dVector zaxis = height_point - center_point;
			ON_Plane planeCir( center_point, zaxis );

			/*ADD CIRCLE FOR CYLINDER'S BASE*/
			ON_Circle circle( planeCir, radius );

			/*ADD CYLINDER*/
			ON_Cylinder cylinder( circle, zaxis.Length() );
			ON_Brep* brep = ON_BrepCylinder( cylinder, TRUE, TRUE );
			unsigned int first_SN;
			unsigned int next_SN;
			if( brep )
			{
				first_SN = CRhinoObject::NextRuntimeObjectSerialNumber();
				/********************/
				/*TRANSLATE CYLINDER*/
				/********************/
				int nIndex1 = plugin.m_dialog->AltezzaFondelloControllo.GetCurSel();
				CString strCBText1;
				plugin.m_dialog->AltezzaFondelloControllo.GetLBText( nIndex1, strCBText1);
				int altfondello = _wtoi(strCBText1);
				ON_wString obj_nameCyl = L"CILINDRO";
								
				
				brep->Translate(ON_3dVector( 0.0, 0.0, -altfondello));
				CRhinoBrepObject* cylinder_object = new CRhinoBrepObject();
				cylinder_object->SetBrep( brep );
				if( context.m_doc.AddObject(cylinder_object) )
				{
					context.m_doc.Redraw();
					next_SN = CRhinoObject::NextRuntimeObjectSerialNumber();
					if( first_SN == next_SN )
					{
						return CRhinoCommand::nothing;
					}
					else
					{
						SetNametoObject(context.m_doc,first_SN,obj_nameCyl,true);			  
					}
				}
				else
				{
					delete cylinder_object;
				}

				/*********************************************/
				/*               DA SISTEMARE                */
				/*********************************************/
				
				CRhinoSnapContext snap;
				bool dec1 = snap.SnapToPoint(ON_3dPoint(63.5, 0.0, (height - altfondello)));
				bool dec2 = snap.SnapToPoint(ON_3dPoint(63.5, 0.0, -altfondello));
				bool dec3 = snap.SnapToPoint(ON_3dPoint(63.5, 0.0, 0.0));
				if(dec1 && dec2)
				{
					CRhinoLinearDimension* dim_obj = new CRhinoLinearDimension();
					ON_Plane plane( ON_zx_plane );
					plane.SetOrigin( ON_3dPoint(63.5, 0.0, 0.0) );
					dim_obj->SetPlane( plane );
					ON_3dPoint pt_1(63.5, 0.0, (height - altfondello));
					ON_3dPoint pt_2(63.5, 0.0, -altfondello);

					double u, v;
					plane.ClosestPointTo( pt_1, &u, &v );
					dim_obj->SetPoint( 0, ON_2dPoint(u, v) );
					dim_obj->SetPoint( 1, ON_2dPoint(u, (v + height/2)) );


					plane.ClosestPointTo( pt_2, &u, &v );
					dim_obj->SetPoint( 2, ON_2dPoint(u, v) );
					dim_obj->SetPoint( 3, ON_2dPoint(u, (v + height/2)) );

					dim_obj->UpdateText();
					 
					if( context.m_doc.AddObject(dim_obj) )
					{
						context.m_doc.Redraw();
					}		
					else
					{
						delete dim_obj;
					}
				}
				/*********************************************/
				/*               DA SISTEMARE                */
				/*********************************************/
				if(dec2 && dec3)
				{
					CRhinoLinearDimension* dim_obj = new CRhinoLinearDimension();
					ON_Plane plane( ON_zx_plane );
					plane.SetOrigin( ON_3dPoint(63.5, 0.0, 0.0) );
					dim_obj->SetPlane( plane );
					ON_3dPoint pt_1(63.5, 0.0, 0.0);
					ON_3dPoint pt_2(63.5, 0.0, -altfondello);

					double u, v;
					plane.ClosestPointTo( pt_1, &u, &v );
					dim_obj->SetPoint( 0, ON_2dPoint(u, v) );
					dim_obj->SetPoint( 1, ON_2dPoint(u, (v + height/2)) );


					plane.ClosestPointTo( pt_2, &u, &v );
					dim_obj->SetPoint( 2, ON_2dPoint(u, v) );
					dim_obj->SetPoint( 3, ON_2dPoint(u, (v + height/2)) );

					dim_obj->UpdateText();
					 
					if( context.m_doc.AddObject(dim_obj) )
					{
						context.m_doc.Redraw();
					}		
					else
					{
						delete dim_obj;
					}
				}
				/*********************************************/
				/*               DA SISTEMARE  By Nello              */
				/*********************************************/
				
				ON_3dPoint provapunto2 = AltezzaTacco;
				ON_3dPoint provapunto(59.5,0,provapunto2.z);
				provapunto.z-=0.7;
				ON_3dPoint pt_1(59.5, 0.0, (height - altfondello));
				CRhinoLinearDimension* dim_obj = new CRhinoLinearDimension();
					ON_Plane plane( ON_zx_plane );
					plane.SetOrigin(pt_1);
					dim_obj->SetPlane( plane );
					//ON_3dPoint pt_1(63.5, 0.0, 0.0);
					ON_3dPoint pt_2 = provapunto;

					double u, v;
					plane.ClosestPointTo( pt_1, &u, &v );
					dim_obj->SetPoint( 0, ON_2dPoint(u, v) );
					dim_obj->SetPoint( 1, ON_2dPoint(u, (v + height/2)) );


					plane.ClosestPointTo( pt_2, &u, &v );
					dim_obj->SetPoint( 2, ON_2dPoint(u, v) );
					dim_obj->SetPoint( 3, ON_2dPoint(u, (v + height/2)) );

					dim_obj->UpdateText();
					 
					if( context.m_doc.AddObject(dim_obj) )
					{
						context.m_doc.Redraw();
					}		
					else
					{
						delete dim_obj;
					}
				
					/*INIZIO FUNZIONE CONTROLLO*/
			
					if ( (height - altfondello)>=provapunto.z+10){
						::RhinoApp().Print( L"Funzione controllo altezza OK");
					}
					else{
						::RhinoApp().Print( L"Funzione controllo altezza NOK: CONTROLLARE!! Il valore della testa e' minore del valore minimo di 10 mm. Occorre diminuire l'altezza del fondello o aumentare l'altezza dello stampo.");
					}


				/*********************************************/
				/*           CREATE FONDELLO PLANE           */
				/*********************************************/

				ON_3dPoint point0((63.5 + 20.0),0.0, 0.0);
				ON_3dPoint point1(-(63.5 + 20.0),0.0, 0.0);
				ON_LineCurve curve0( point0, point1 );

				context.m_doc.AddCurveObject(curve0);
				context.m_doc.Redraw();


				/******************************************************/
				/*****************************/
				/*USER GIVES NAME TO SURFACES*/ 
				/*****************************/
				unsigned int first_sn;
				unsigned int next_sn;
				ON_wString obj_name;
				object_count = context.m_doc.LookupObject( layer, objects );
				for(int i = 0; i < object_count; i++ )
				{
					object = objects[ i ];
					first_sn = CRhinoObject::NextRuntimeObjectSerialNumber();

					/*******************************/
					/*TRY CASTING AS A CURVE OBJECT*/ 
					/*******************************/
					curve_obj = CRhinoCurveObject::Cast( object );
					if( curve_obj )
					{
						const ON_Geometry* geo = curve_obj->Geometry();
						const ON_Curve* curve00 = ON_Curve::Cast(geo); 
						ON_3dPoint point  = curve00->PointAt(0.0);
						ON_3dPoint point_ = curve00->PointAt(1.0);
						if((point.z + point_.z)/2 > 0.0)
						{
							obj_name = L"SURFPV";
						}
						else
						{
							obj_name = L"SURFFO";
						}
						ON_3dPoint point0(point.x, (point.y + 70.0), point.z);
						ON_3dPoint point1(point.x, (point.y - 70.0), point.z);
						ON_LineCurve* curve = new ON_LineCurve();
						curve->SetStartPoint(point0);
						curve->SetEndPoint(point1);
						ON_SumSurface sumSurf0;
						sumSurf0.Create(*curve, *curve00);

						if( context.m_doc.AddSurfaceObject(sumSurf0) )
						{

							context.m_doc.Redraw();
							next_sn = CRhinoObject::NextRuntimeObjectSerialNumber();
							if( first_sn == next_sn )
							{
								return CRhinoCommand::nothing;
							}
							else
							{
								SetNametoObject(context.m_doc,first_sn,obj_name,true);			  
							}
						}

					}
				}/*CLOSED FOR*/

				//int R = 0;
				//object_count = context.m_doc.LookupObject( layer, objects );
				//for(int i = 0; i < object_count; i++)
				//{
				//	object = objects[ i ];
				//	const CRhinoCurveObject* surface_obj = CRhinoCurveObject::Cast(object);
				//	if(surface_obj)
				//	{
				//		R++;
				//	}
				//}

				 // // Get the string entered by the user
				 // ON_wString obj_name = gs.String();
				 // obj_name.TrimLeftAndRight();
				 //
				 // // Is name the same?
				 // if( obj_name.Compare(obj_attribs.m_name) == 0 )
					//return CRhinoCommand::nothing;
				 //
				 // // Modify the attributes of the object
				 // obj_attribs.m_name = obj_name;
				 // context.m_doc.ModifyObjectAttributes( objref, obj_attribs );
				 // if(selectobjectbyuuid_s(context.m_doc,obj_Surf[j],false))
				 // {
					//int R = 0;
				 // }



			  
			  ON_wString obj_Surf[2];
			  ON_wString name;
              obj_Surf[0] = L"SURFPV";
			  obj_Surf[1] = L"SURFFO";
			  object_count = context.m_doc.LookupObject( layer, objects );
			  int R = 0;
			  /************************/
			  /*TRY SPLITTING THE BREP*/
			  /************************/
			  for(int j = 0; j < 2; j++)
			  {
				  for(int i = 0; i < object_count; i++)
				  {
					  object = objects[ i ];

					  /*MAKE COPY OF OBJECT ATTRIBUTES. THIS OBJECTS*/ 
					  /*HOLDS AN OBJECT'S USER-DEFINED NAME.*/ 
					  ON_3dmObjectAttributes obj_attribs = object->Attributes();
			
					  name = object->Attributes().m_name;

					  surface_obj = CRhinoSurfaceObject::Cast( object );
					  if( surface_obj && !surface_obj->IsSolid())
					  {
						  ON_wString obj_SurfLoc = obj_Surf[j];

						  /*IS THE CUTTING SURFACE?*/
						  if( obj_SurfLoc.Compare(name) == 0 )
						  {							
							R++;
						  }
					  }/*CHIUSURA IF SUPERFICIE*/
				  } 
				 

				 // /************************/
				 // /*PICK THE BREP TO SPLIT*/ 
				 // /************************/
				 // CRhinoGetObject go;
				 // go.SetCommandPrompt( L"SELECT SOLID TO SPLIT" );
				 // go.SetGeometryFilter( CRhinoGetObject::polysrf_object  );//CRhinoGetObject::surface_object | CRhinoGetObject::polysrf_object 
				 // go.GetObjects( 1, 1 );
				 // if( go.CommandResult() != success )
				 // {
					//return go.CommandResult();
				 // }
				 // else
				 // {
					//	RhinoMessageBox(L"CYLINDER IS SELECTED", PlugIn()->PlugInName(), MB_OK | MB_ICONEXCLAMATION );
				 // }
				 //
				 // const CRhinoObjRef& split_ref = go.Object(0);
				 //
				 // const CRhinoObject* split_object = split_ref.Object();
				 // if( !split_object )
				 // {
					//return failure;
				 // }
				 //
				 // const ON_Brep* split = split_ref.Brep();
				 // if( !split )
				 // {
					//return failure;
				 // }

				 // ON_SimpleArray<ON_Brep*> pieces;
				 // double tol = context.m_doc.AbsoluteTolerance();
			 
				 // /***********************/
				 // /*PICK THE CUTTING BREP*/
				 // /***********************/
				 // go.SetCommandPrompt( L"SELECT CUTTING SURFACE OR POLYSUFACE" );
				 // go.SetGeometryFilter( CRhinoGetObject::surface_object | CRhinoGetObject::polysrf_object  ); 
				 // go.EnablePreSelect( FALSE );
				 // go.EnableDeselectAllBeforePostSelect( FALSE );
				 // go.GetObjects( 1, 2 );
				 // if( go.CommandResult() != success )
				 // {
					//return go.CommandResult();
				 // }

				 // const ON_Brep* cutter = go.Object(0).Brep();
				 // if( !cutter )
				 // {
					//return failure;
				 // }
				 //

				 // if( !RhinoBrepSplit(*split, *cutter, tol, pieces) )
				 // {
					//RhinoApp().Print( L"UNABLE TO SPLIT BREP.\n" );
				 // }
				 //
				 // int i, count = pieces.Count();
				 // if( count == 0 | count == 1 )
				 // {
					//if( count == 1 )
					//{
					//  delete pieces[0];
					//}
					//return nothing;
				 // }
				 //
				 // CRhinoObjectAttributes attrib = split_object->Attributes();
				 // attrib.m_uuid = ON_nil_uuid; 
				 //
				 // const CRhinoObjectVisualAnalysisMode* vam_list = split_object->m_analysis_mode_list;
				 //
				 // for( i = 0; i < count; i++ )
				 // {
					//CRhinoBrepObject* brep_object = new CRhinoBrepObject( attrib );
					//if( brep_object )
					//{
					//  brep_object->SetBrep( pieces[i] );
					//  if( context.m_doc.AddObject(brep_object) )
					//  {
					//	RhinoCopyAnalysisModes( vam_list, brep_object );

					//  }
					//  else
					//  {
					//	delete brep_object;
					//  }
					//}
				 // }
				 //
				 // context.m_doc.DeleteObject( split_ref ); 
				 // context.m_doc.Redraw();
			  }



		    /*CREATE A NEW LAYER*/
			  ON_Layer layer;
			  int layer_index = 0;
			  ON_Color color = ON_Color(0, 0, 0);
			  ON_wString layer_name_FONDELLO = L"FONDELLO";
			  layer.SetLayerName( layer_name_FONDELLO );
			  layer.SetPlotColor(color.Green());

			/*ADD THE LAYER TO THE LAYER TABLE*/ 
			  layer_index = context.m_doc.m_layer_table.AddLayer( layer );

			  ON_wString layer_name_MATRICE  = L"MATRICE";
			  layer.SetLayerName( layer_name_MATRICE );
			  layer.SetColor(color.Red());

			/*ADD THE LAYER TO THE LAYER TABLE*/ 
			  layer_index = context.m_doc.m_layer_table.AddLayer( layer );


			  ON_wString layer_name_FISSO    = L"FISSO";
			  layer.SetLayerName( layer_name_FISSO );
			  layer.SetColor(color.Blue());

			/*ADD THE LAYER TO THE LAYER TABLE*/ 
			  layer_index = context.m_doc.m_layer_table.AddLayer( layer );
	  
			  context.m_doc.Redraw();
			/*********************************************************/
			}
		}/*CLOSED IF OVER CHECKING BREP COUNT OBJECT*/
		else
		{
			RhinoMessageBox(L"THERE IS ALREADY A CYLINDER OBJECT", PlugIn()->PlugInName(), MB_OK | MB_ICONEXCLAMATION );
		}
	}
	/**********************************************************************/



  return CRhinoCommand::success;
}
Пример #4
0
void compute_formfactor(Element *e_src, Element *e_dst, Interaction *inter, long process_id)
{
    float ff_c, ff_1, ff_2, ff_3 ;
    float ff_c1, ff_c2, ff_c3, ff_avg ;
    Vertex pc_src, pc_dst ;
    Vertex pc1_src, pc2_src, pc3_src ;
    float ff_min, ff_max, ff_err ;

    /* Estimate FF using disk approximation */
    /* (1) Compute FF(diff-disc) from the center of src to the destination */
    four_center_points( &e_src->ev1->p, &e_src->ev2->p, &e_src->ev3->p,
                       &pc_src, &pc1_src, &pc2_src, &pc3_src ) ;
    center_point( &e_dst->ev1->p, &e_dst->ev2->p, &e_dst->ev3->p, &pc_dst ) ;
    ff_c  = compute_diff_disc_formfactor( &pc_src,  e_src, &pc_dst, e_dst, process_id ) ;
    ff_c1 = compute_diff_disc_formfactor( &pc1_src, e_src, &pc_dst, e_dst, process_id ) ;
    ff_c2 = compute_diff_disc_formfactor( &pc2_src, e_src, &pc_dst, e_dst, process_id ) ;
    ff_c3 = compute_diff_disc_formfactor( &pc3_src, e_src, &pc_dst, e_dst, process_id ) ;
    if( ff_c  < 0 ) ff_c  = 0 ;
    if( ff_c1 < 0 ) ff_c1 = 0 ;
    if( ff_c2 < 0 ) ff_c2 = 0 ;
    if( ff_c3 < 0 ) ff_c3 = 0 ;
    ff_avg = (ff_c + ff_c1 + ff_c2 + ff_c3) * (float)0.25 ;
    ff_min = ff_max = ff_c ;
    if( ff_min > ff_c1 ) ff_min = ff_c1 ;
    if( ff_min > ff_c2 ) ff_min = ff_c2 ;
    if( ff_min > ff_c3 ) ff_min = ff_c3 ;
    if( ff_max < ff_c1 ) ff_max = ff_c1 ;
    if( ff_max < ff_c2 ) ff_max = ff_c2 ;
    if( ff_max < ff_c3 ) ff_max = ff_c3 ;

    /* (2) Compute FF(diff-disc) from the 3 vertices of the source */
    ff_1 = compute_diff_disc_formfactor( &e_src->ev1->p, e_src,
                                        &pc_dst, e_dst, process_id ) ;
    ff_2 = compute_diff_disc_formfactor( &e_src->ev2->p, e_src,
                                        &pc_dst, e_dst, process_id ) ;
    ff_3 = compute_diff_disc_formfactor( &e_src->ev3->p, e_src,
                                        &pc_dst, e_dst, process_id ) ;

    /* (3) Find FF min and max */
    ff_min = ff_max = ff_c ;
    if( ff_min > ff_1 ) ff_min = ff_1 ;
    if( ff_min > ff_2 ) ff_min = ff_2 ;
    if( ff_min > ff_3 ) ff_min = ff_3 ;
    if( ff_max < ff_1 ) ff_max = ff_1 ;
    if( ff_max < ff_2 ) ff_max = ff_2 ;
    if( ff_max < ff_3 ) ff_max = ff_3 ;

    /* (4) Clip FF(diff-disc) if it is negative */
    if( ff_avg < 0 )
        ff_avg = 0 ;
    inter->formfactor_out = ff_avg ;

    /* (5) Then find maximum difference from the FF at the center */
    ff_err = (ff_max - ff_avg) ;
    if( ff_err < (ff_avg - ff_min) )
        ff_err = ff_avg - ff_min ;
    inter->formfactor_err = ff_err ;

    /* (6) Correct visibility if partially visible */
    if( (ff_avg < 0) && (inter->visibility == 0) )
        /* All ray missed the visible portion of the elements.
           Set visibility to a non-zero value manually */
        /** inter->visibility = FF_VISIBILITY_ERROR **/ ;

    /* (7) Fill destination */
    inter->destination = e_dst ;
}